[Armadeus-commitlog] SF.net SVN: armadeus: [780] trunk/target/linux/modules
Brought to you by:
sszy
|
From: <Fa...@us...> - 2008-04-02 08:10:00
|
Revision: 780
http://armadeus.svn.sourceforge.net/armadeus/?rev=780&view=rev
Author: FabM
Date: 2008-04-02 01:00:54 -0700 (Wed, 02 Apr 2008)
Log Message:
-----------
[LINUX][DRIVERS] fpga special drivers dependance
Modified Paths:
--------------
trunk/target/linux/modules/Kconfig
trunk/target/linux/modules/Makefile
Added Paths:
-----------
trunk/target/linux/modules/fpga/
trunk/target/linux/modules/fpga/Kconfig
trunk/target/linux/modules/fpga/Wb_button/
trunk/target/linux/modules/fpga/Wb_button/Kconfig
trunk/target/linux/modules/fpga/Wb_button/Makefile
trunk/target/linux/modules/fpga/Wb_button/button.c
trunk/target/linux/modules/fpga/Wb_button/button.h
trunk/target/linux/modules/fpga/Wb_button/button_specific.h
trunk/target/linux/modules/fpga/Wb_button/testbutton.c
trunk/target/linux/modules/fpga/Wb_led/
trunk/target/linux/modules/fpga/Wb_led/Kconfig
trunk/target/linux/modules/fpga/Wb_led/Makefile
trunk/target/linux/modules/fpga/Wb_led/led.c
trunk/target/linux/modules/fpga/Wb_led/led.h
trunk/target/linux/modules/fpga/Wb_led/led.mod.c
trunk/target/linux/modules/fpga/Wb_led/led_specific.h
trunk/target/linux/modules/fpga/fpga_devtools/
trunk/target/linux/modules/fpga/fpga_devtools/Kconfig
trunk/target/linux/modules/fpga/fpga_devtools/Makefile
trunk/target/linux/modules/fpga/fpga_devtools/fpga-loader.c
trunk/target/linux/modules/fpga/fpga_devtools/fpga-loader.h
trunk/target/linux/modules/fpga/fpga_devtools/fpgaloader.sh
trunk/target/linux/modules/fpga/fpga_devtools/target-fpga-loader.c
trunk/target/linux/modules/fpga/fpga_devtools/target-fpga-loader.h
trunk/target/linux/modules/fpga/fpga_devtools/xilinx-fpga-loader.c
trunk/target/linux/modules/fpga/fpga_devtools/xilinx-fpga-loader.h
trunk/target/linux/modules/fpga/keypad/
trunk/target/linux/modules/fpga/keypad/Kconfig
trunk/target/linux/modules/fpga/keypad/Makefile
trunk/target/linux/modules/fpga/keypad/imxkeypad.c
trunk/target/linux/modules/fpga/ps2keyboard/
trunk/target/linux/modules/fpga/ps2keyboard/Kconfig
trunk/target/linux/modules/fpga/ps2keyboard/Makefile
trunk/target/linux/modules/fpga/ps2keyboard/README
trunk/target/linux/modules/fpga/ps2keyboard/core.c
Removed Paths:
-------------
trunk/target/linux/modules/fpga_devtools/
trunk/target/linux/modules/keypad/
trunk/target/linux/modules/ps2keyboard/
Modified: trunk/target/linux/modules/Kconfig
===================================================================
--- trunk/target/linux/modules/Kconfig 2008-04-02 07:40:22 UTC (rev 779)
+++ trunk/target/linux/modules/Kconfig 2008-04-02 08:00:54 UTC (rev 780)
@@ -6,15 +6,10 @@
#
config ARMADEUS_DRIVERS
- boolean
- default n
-
-config ARMADEUS_DRIVERS
boolean "Support for specific Armadeus drivers"
default n
---help---
-
source "drivers/armadeus/generic/Kconfig"
source "drivers/armadeus/gpio/Kconfig"
@@ -22,12 +17,8 @@
comment "FPGA related"
depends on ARMADEUS_DRIVERS
-source "drivers/armadeus/fpga_devtools/Kconfig"
+source "drivers/armadeus/fpga/Kconfig"
-source "drivers/armadeus/keypad/Kconfig"
-
-source "drivers/armadeus/ps2keyboard/Kconfig"
-
comment "Handheld related"
depends on ARMADEUS_DRIVERS
@@ -40,6 +31,5 @@
source "drivers/armadeus/isp1761/Kconfig"
-
endmenu
Modified: trunk/target/linux/modules/Makefile
===================================================================
--- trunk/target/linux/modules/Makefile 2008-04-02 07:40:22 UTC (rev 779)
+++ trunk/target/linux/modules/Makefile 2008-04-02 08:00:54 UTC (rev 780)
@@ -7,7 +7,8 @@
# Part executed when called from kernel build system:
ifneq ($(KERNELRELEASE),)
-obj-$(CONFIG_ARMADEUS_DRIVERS) += gpio/ ps2keyboard/ keypad/ fpga_devtools/ pwm/ backlight/ isp1761/
+obj-$(CONFIG_ARMADEUS_DRIVERS) += gpio/ pwm/ backlight/ isp1761/ \
+ fpga/ps2keyboard/ fpga/keypad/ fpga/fpga_devtools/ fpga/Wb_led/ fpga/Wb_button/
# Part execute when called from standard make in this directory:
else
Added: trunk/target/linux/modules/fpga/Kconfig
===================================================================
--- trunk/target/linux/modules/fpga/Kconfig (rev 0)
+++ trunk/target/linux/modules/fpga/Kconfig 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,25 @@
+#
+# Armadeus custom drivers configuration
+#
+
+menu "FPGA Drivers "
+
+#
+config ARMADEUS_FPGA_DRIVERS
+ boolean "Support for FPGA specific drivers"
+ default n
+ ---help---
+ All drivers for FPGA components
+
+source "drivers/armadeus/fpga/fpga_devtools/Kconfig"
+
+source "drivers/armadeus/fpga/keypad/Kconfig"
+
+source "drivers/armadeus/fpga/ps2keyboard/Kconfig"
+
+source "drivers/armadeus/fpga/Wb_led/Kconfig"
+
+source "drivers/armadeus/fpga/Wb_button/Kconfig"
+
+endmenu
+
Added: trunk/target/linux/modules/fpga/Wb_button/Kconfig
===================================================================
--- trunk/target/linux/modules/fpga/Wb_button/Kconfig (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_button/Kconfig 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,8 @@
+#
+#
+
+config ARMADEUS_BUTTON_DRIVER
+ tristate "Wishbone Button driver"
+ default n
+ depends on ARMADEUS_FPGA_DRIVERS
+ ---help---
Added: trunk/target/linux/modules/fpga/Wb_button/Makefile
===================================================================
--- trunk/target/linux/modules/fpga/Wb_button/Makefile (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_button/Makefile 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,38 @@
+#
+# Makefile for the Armadeus Wb_button drivers
+#
+
+BASE_DIR="../../../../../buildroot/"
+
+REL=`grep "BR2_PACKAGE_LINUX_VERSION=" $(BASE_DIR).config | \
+ sed "s/BR2_PACKAGE_LINUX_VERSION=\\"//" | sed "s/\\"//"`
+
+ARMADEUS_KERNEL_DIR=$(BASE_DIR)build_arm/linux-$(REL)
+
+ifneq ($(KERNELRELEASE),)
+
+obj-$(CONFIG_ARMADEUS_BUTTON_DRIVER) += button.o
+
+# Part executed when called from standard make in this directory:
+# (preferably use Makefile in parent directory)
+
+else
+
+KDIR := $(ARMADEUS_KERNEL_DIR)
+PWD := $(shell pwd)
+
+default:
+ $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+ -cp button.ko /tftpboot/
+
+test:
+ ~/armadeus/buildroot/build_arm/staging_dir/bin/arm-linux-gcc testbutton.c -o testbutton
+ chmod 755 testbutton
+ cp testbutton /tftpboot/
+
+clean:
+ rm -f *.*o \
+ rm -f Module.symvers
+
+endif
+
Property changes on: trunk/target/linux/modules/fpga/Wb_button/Makefile
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/target/linux/modules/fpga/Wb_button/button.c
===================================================================
--- trunk/target/linux/modules/fpga/Wb_button/button.c (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_button/button.c 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,200 @@
+/* button.c
+ * Driver for bus_led fpga IP
+ * Fabien Marteau <fab...@ar...>
+ */
+
+#include "button.h"
+
+/*********************************
+ * simple fpga read/write
+ *********************************/
+
+
+static ssize_t button_fpga_read(void * addr,u16 *data,struct button_dev *dev){
+ *data = ioread16(addr);/* read the button value */
+ return 2;
+}
+
+
+static ssize_t button_fpga_write(void * addr,u16 *data,struct button_dev *dev){
+ ssize_t retval;
+
+ iowrite16(*data,addr);/* write the button value */
+ retval = 2;
+ return retval;
+}
+
+/**********************************
+ * irq management
+ * awake read process
+ * ********************************/
+
+static irqreturn_t fpga_interrupt(int irq,void *dev_id,struct pt_regs *reg){
+ struct button_dev *ldev = dev_id;
+ u16 data;
+
+ /* wake up reading process */
+ if(ldev->reading)up(&ldev->sem);
+ /* acknowledge irq_mngr */
+ data=1;
+ BUG_ON((button_fpga_write(ldev->fpga_virtual_base_address + FPGA_IRQ_ACK,&data,ldev))<0);
+
+ return IRQ_HANDLED;
+}
+
+/***********************************
+ * characters file /dev operations
+ * *********************************/
+ssize_t button_read(struct file *fildes, char __user *buff, size_t count, loff_t *offp){
+ struct button_dev *ldev = fildes->private_data;
+ u16 data=0;
+ ssize_t retval = 0;
+ DEFINE_WAIT(wait);
+
+ ldev->reading = 1;
+
+ if(*offp + count >= 1) /* Only one word can be read */
+ count = 1 - *offp;
+
+ if((retval=down_interruptible(&ldev->sem))<0)
+ goto out;
+
+ if((retval = button_fpga_read(ldev->fpga_virtual_base_address + FPGA_BUTTON,&data,ldev))<0)
+ goto out;
+
+ /* return data for user */
+ if(copy_to_user(buff,&data,2)){
+ printk(KERN_WARNING "read : copy to user data error\n");
+ retval = -EFAULT;
+ goto out;
+ }
+
+ *offp = *offp + count;
+ retval = 1;
+
+out:
+ PDEBUG("read : Return value %d\n",(int)retval);
+ ldev->reading = 0;
+ return retval;
+}
+
+
+int button_open(struct inode *inode, struct file *filp){
+ /* Allocate and fill any data structure to be put in filp->private_data */
+ filp->private_data = container_of(inode->i_cdev,struct button_dev, cdev);
+ PDEBUG( "file opened\n");
+ return 0;
+}
+
+/* ******************************
+ * Init and release functions
+ * ******************************/
+int button_release(struct inode *inode, struct file *filp){
+ PDEBUG( "released\n");
+ return 0;
+}
+
+/**********************************
+ * Module management
+ **********************************/
+static int __init button_init(void){
+
+ int result; /* error return */
+ int button_major,button_minor;
+ u16 data;
+ struct button_dev *sdev;
+
+ button_major = 252;
+ button_minor = 0;
+
+ /* Allocate a private structure and reference it as driver's data */
+ sdev = (struct button_dev *)kmalloc(sizeof(struct button_dev),GFP_KERNEL);
+ if(sdev == NULL){
+ printk(KERN_WARNING "button: unable to allocate private structure\n");
+ return -ENOMEM;
+ }
+
+ /* Get the major and minor device numbers */
+ PDEBUG("Get the major and minor device numbers\n");
+ if(button_major){
+ devno = MKDEV(button_major,button_minor);
+ result = register_chrdev_region(devno, N_DEV,BUTTON_NAME);
+ }else{
+ result = alloc_chrdev_region(&devno,button_minor,N_DEV,BUTTON_NAME);
+ button_major = MAJOR(devno);
+ }
+ printk(KERN_INFO "button: MAJOR: %d MINOR: %d\n",MAJOR(devno),MINOR(devno));
+ if(result < 0){
+ printk(KERN_WARNING "button: can't get major %d\n",button_major);
+ }
+
+ /* Init the cdev structure */
+ PDEBUG("Init the cdev structure\n");
+ cdev_init(&sdev->cdev,&button_fops);
+ sdev->cdev.owner = THIS_MODULE;
+
+ /* Add the device to the kernel, connecting cdev to major/minor number */
+ PDEBUG("Add the device to the kernel, connecting cdev to major/minor number \n");
+ result = cdev_add(&sdev->cdev,devno,1);
+ if(result < 0)printk(KERN_WARNING "button: can't add cdev\n");
+
+ /* Requested I/O memory */
+ sdev->fpga_virtual_base_address = (void*)IMX_CS1_VIRT;
+
+ /* irq registering */
+ if(request_irq(IRQ_GPIOA(1),(irq_handler_t)fpga_interrupt,IRQF_SHARED,FPGA_IRQ_NAME,sdev)<0){
+ printk(KERN_ERR "Can't request fpga irq\n");
+ goto error;
+ }
+ /* irq acknowledge */
+ data=1;
+ if((result=button_fpga_write(sdev->fpga_virtual_base_address + FPGA_IRQ_ACK,&data,sdev))<0)
+ goto error;
+ /* irq unmask */
+ data=1;
+ if((result=button_fpga_write(sdev->fpga_virtual_base_address + FPGA_IRQ_MASK,&data,sdev))<0)
+ goto error;
+
+ /* initiate mutex locked */
+ sdev->reading = 0;
+ init_MUTEX_LOCKED(&sdev->sem);
+
+
+ /* OK module inserted ! */
+ buttondev = sdev;
+ printk(KERN_INFO "button module insered\n");
+ return 0;
+
+
+error:
+ printk(KERN_ERR "%s: not inserted\n",BUTTON_NAME);
+ free_all();
+ return result;
+}
+
+static void __exit button_exit(void){
+ free_all();
+}
+
+static void free_all(void){
+ struct button_dev *sdev = buttondev;
+
+ /* free irq*/
+ free_irq(IRQ_GPIOA(1),sdev);
+
+ /* delete the cdev structure */
+ cdev_del(&sdev->cdev);
+
+ /* Free the allocated memory */
+ kfree(sdev);
+
+ /* Release I/O memories */
+ release_mem_region(FPGA_BASE_ADDR,FPGA_MEM_SIZE);
+
+ /* free major and minor number */
+ unregister_chrdev_region(devno,N_DEV);
+ printk(KERN_INFO "button module deleted\n");
+}
+
+module_init(button_init);
+module_exit(button_exit);
Added: trunk/target/linux/modules/fpga/Wb_button/button.h
===================================================================
--- trunk/target/linux/modules/fpga/Wb_button/button.h (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_button/button.h 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,107 @@
+/* button.h
+ * Driver for Wb_button IP
+ * Fabien Marteau <fab...@ar...>
+ * 28 mars 2008
+ */
+
+
+#ifndef __BUTTON_H__
+#define __BUTTON_H__
+
+#include "button_specific.h"
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+#include <linux/config.h>
+#endif
+
+/* form module/drivers */
+#include <linux/init.h>
+#include <linux/module.h>
+
+/* for file operations */
+#include <linux/fs.h>
+#include <linux/cdev.h>
+
+/* copy_to_user function */
+#include <asm/uaccess.h>
+
+/* request_mem_region */
+#include <linux/ioport.h>
+
+/* readw() writew() */
+#include <asm/io.h>
+
+/* hardware addresses */
+#include <asm/hardware.h>
+
+/* interruptions */
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <linux/wait.h>
+#include <asm/semaphore.h>
+
+/* measure time */
+#include <linux/jiffies.h>
+#endif
+
+/* for debugging messages*/
+#define BUTTON_DEBUG
+
+#undef PDEBUG
+#ifdef BUTTON_DEBUG
+# ifdef __KERNEL__
+ /* for kernel spage */
+# define PDEBUG(fmt,args...) printk(KERN_DEBUG "button : " fmt, ##args)
+# else
+ /* for user space */
+# define PDEBUG(fmt,args...) printk(stderr, fmt, ##args)
+# endif
+#else
+# define PDEBUG(fmt,args...) /* no debbuging message */
+#endif
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Fabien Marteau <fab...@ar...> - ARMadeus Systems");
+MODULE_DESCRIPTION("button device driver");
+
+/* main device structure */
+struct button_dev{
+ struct cdev cdev; /* Char device structure */
+ struct semaphore sem; /* Mutex */
+ void * fpga_virtual_base_address; /* fpga register base address*/
+ wait_queue_head_t button_queue;
+ u8 reading;
+};
+
+/* major and minor number */
+
+#define N_DEV 1
+static dev_t devno; /* to store Major and minor numbers */
+static struct button_dev *buttondev;
+#define BUTTON_LENGTH 1
+struct resource *mem; /* pointer to fpga button */
+
+
+/* to read write button register */
+ssize_t button_read(struct file *fildes, char __user *buff,
+ size_t count, loff_t *offp);
+
+int button_open(struct inode *inode, struct file *filp);
+
+int button_release(struct inode *, struct file *filp);
+
+struct file_operations button_fops = {
+ .owner = THIS_MODULE,
+ .read = button_read,
+ .open = button_open,
+ .release = button_release,
+};
+
+static irqreturn_t fpga_interrupt(int irq,void *stuff,struct pt_regs *reg);
+
+static void free_all(void);
+
+static ssize_t button_fpga_read(void * addr, u16 *data , struct button_dev *dev);
+static ssize_t button_fpga_write(void * addr, u16 *data, struct button_dev *dev);
Added: trunk/target/linux/modules/fpga/Wb_button/button_specific.h
===================================================================
--- trunk/target/linux/modules/fpga/Wb_button/button_specific.h (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_button/button_specific.h 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,14 @@
+#define BUTTON_NAME "button"
+#define FPGA_BUTTON 8
+#define FPGA_IRQ_MASK 0
+#define FPGA_IRQ_PEND 2
+#define FPGA_IRQ_ACK 2
+
+/* Fpga base address for led */
+#define FPGA_BASE_ADDR IMX_CS1_PHYS
+#define FPGA_MEM_SIZE IMX_CS1_SIZE
+#define FPGA_IRQ_NAME "fpga"
+
+/* interrupt position in irq_mngr */
+#define WB_BUTTON_IRQ 0x0001
+
Added: trunk/target/linux/modules/fpga/Wb_button/testbutton.c
===================================================================
--- trunk/target/linux/modules/fpga/Wb_button/testbutton.c (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_button/testbutton.c 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,67 @@
+/* a little program to test button driver
+ * Fabien Marteau <fab...@ar...>
+ * 7 march 2008
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* file management */
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* as name said */
+#include <signal.h>
+
+/* sleep */
+#include <unistd.h>
+
+int fled;
+
+void quit(int pouet){
+ close(fled);
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned short i,j;
+
+ /* quit when Ctrl-C pressed */
+ signal(SIGINT, quit);
+
+ j=0;
+
+ printf( "Testing button driver\n" );
+
+ if(argc < 2){
+ perror("invalide arguments number\ntestled <button_filename>\n");
+ exit(EXIT_FAILURE);
+ }
+
+ fled=open(argv[1],O_RDWR);
+ if(fled<0){
+ perror("can't open file\n");
+ exit(EXIT_FAILURE);
+ }
+
+ while(1){
+ i = (i==0)?1:0;
+ fflush(stdout);
+
+ /* read value */
+ if(read(fled,&j,1)<0){
+ perror("read error\n");
+ exit(EXIT_FAILURE);
+ }
+ printf("Read %d\n",j);
+
+ if(lseek(fled,0,SEEK_SET)<0){
+ perror("lseek error\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ close(fled);
+ exit(0);
+}
Added: trunk/target/linux/modules/fpga/Wb_led/Kconfig
===================================================================
--- trunk/target/linux/modules/fpga/Wb_led/Kconfig (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_led/Kconfig 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,8 @@
+#
+#
+
+config ARMADEUS_LED_DRIVER
+ tristate "Wishbone Led driver"
+ default n
+ depends on ARMADEUS_FPGA_DRIVERS
+ ---help---
Added: trunk/target/linux/modules/fpga/Wb_led/Makefile
===================================================================
--- trunk/target/linux/modules/fpga/Wb_led/Makefile (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_led/Makefile 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,37 @@
+#
+# Makefile for the Armadeus Wb_led drivers
+#
+
+BASE_DIR="../../../../../buildroot/"
+
+REL=`grep "BR2_PACKAGE_LINUX_VERSION=" $(BASE_DIR).config | \
+ sed "s/BR2_PACKAGE_LINUX_VERSION=\\"//" | sed "s/\\"//"`
+
+ARMADEUS_KERNEL_DIR=$(BASE_DIR)build_arm/linux-$(REL)
+
+ifneq ($(KERNELRELEASE),)
+
+obj-$(CONFIG_ARMADEUS_LED_DRIVER) += led.o
+
+# Part executed when called from standard make in this directory:
+# (preferably use Makefile in parent directory)
+
+else
+KDIR := $(ARMADEUS_KERNEL_DIR)
+PWD := $(shell pwd)
+
+default:
+ $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+ -cp led.ko /tftpboot/
+
+test:
+ ~/armadeus/buildroot/build_arm/staging_dir/bin/arm-linux-gcc testled.c -o testled
+ chmod 755 testled
+ cp testled /tftpboot/
+
+clean:
+ rm -f *.*o \
+ rm -f Module.symvers
+
+endif
+
Property changes on: trunk/target/linux/modules/fpga/Wb_led/Makefile
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/target/linux/modules/fpga/Wb_led/led.c
===================================================================
--- trunk/target/linux/modules/fpga/Wb_led/led.c (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_led/led.c 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,280 @@
+/* led.c
+ * Driver for bus_led fpga IP
+ * Fabien Marteau <fab...@ar...>
+ */
+
+#include "led.h"
+
+/*********************************
+ * simple fpga read/write
+ *********************************/
+
+static ssize_t led_fpga_read(void * addr,u16 *data,struct led_dev *dev){
+ *data = ioread16(addr);/* read the led value */
+ // PDEBUG( "read : value read : %x\n",*data);
+ return 2;
+}
+
+static ssize_t led_fpga_write(void * addr,u16 *data,struct led_dev *dev){
+ ssize_t retval;
+
+ iowrite16(*data,addr);/* write the led value */
+ retval = 2;
+ return retval;
+}
+
+/* *********************************
+ * Sysfs operations
+ * *********************************/
+
+static void kobj_release(struct kobject *kobj){
+ PDEBUG("led kobject released\n");
+}
+
+static int init_sysinterface(struct led_dev *ldev){
+ int ret = 0;
+
+ /* initializing kobject to 0 */
+ memset(&ldev->kobj,0,sizeof(struct kobject));
+ /* set kobject name */
+ if(unlikely(ret = kobject_set_name(&ldev->kobj,LED_NAME)))
+ goto out;
+ /* register */
+ if(unlikely(ret=kobject_register(&ldev->kobj)))
+ goto out;
+ /* register the kobj_type */
+ ldev->kobj.ktype = &kobjtype;
+ /* add status attribute */
+ if(unlikely(ret=sysfs_create_file(&ldev->kobj,&led_status_attr)));
+
+out:
+ return ret;
+}
+
+static ssize_t led_show_status(struct kobject *kobj,struct attribute *attr,char *buf){
+ ssize_t ret_size = 0;
+ struct led_dev *dev;
+ u16 data;
+
+ dev = container_of(kobj,struct led_dev,kobj);
+
+ if(down_interruptible(&dev->sem)){ /* take mutex */
+ printk(KERN_WARNING "led_show_status:can't take mutex\n");
+ return -ERESTARTSYS;
+ }
+
+ if((ret_size=led_fpga_read(dev->fpga_virtual_base_address + FPGA_LED,&data,dev))<0)
+ goto out;
+
+ PDEBUG("data : %d\n",data);
+ if(data&0x0001)ret_size = (ssize_t)sprintf(buf,"1\n");
+ else ret_size = (ssize_t)sprintf(buf,"0\n");
+
+out:
+ up(&dev->sem);
+ return ret_size;
+}
+
+static ssize_t led_store_status(struct kobject *kobj,struct attribute *attr,
+ const char *buff, size_t size){
+ struct led_dev *ldev = container_of(kobj,struct led_dev,kobj);
+ u16 data;
+
+ if(buff[0]=='1')
+ data=0x0001;
+ else if(buff[0]=='0')
+ data=0x0000;
+ else
+ return size;
+
+ if(down_interruptible(&ldev->sem))
+ return -ERESTARTSYS;
+
+ size=led_fpga_write(ldev->fpga_virtual_base_address + FPGA_LED,&data,ldev);
+
+ up(&ldev->sem);
+ return size ;
+}
+
+/***********************************
+ * characters file /dev operations
+ * *********************************/
+ssize_t led_read(struct file *fildes, char __user *buff, size_t count, loff_t *offp){
+ struct led_dev *ldev = fildes->private_data;
+ u16 data=0;
+ ssize_t retval = 0;
+
+ PDEBUG( "read : offset %d, count %d\n",(int)*offp,(int)count);
+ if(down_interruptible(&ldev->sem)) /* take mutex */
+ return -ERESTARTSYS;
+ if(*offp >= 1){ /* offset must be 0 or 1 */
+ goto out;
+ }
+ if(*offp + count >= 1) /* Only one word can be read */
+ count = 1 - *offp;
+
+ if((retval = led_fpga_read(ldev->fpga_virtual_base_address + FPGA_LED,&data,ldev))<0)
+ goto out;
+
+ /* return data for user */
+ if(copy_to_user(buff,&data,2)){
+ printk(KERN_WARNING "read : copy to user data error\n");
+ retval = -EFAULT;
+ goto out;
+ }
+
+ *offp = *offp + count;
+ retval = 1;
+
+out:
+ up(&ldev->sem); /* free mutex */
+ PDEBUG("read : Return value %d\n",(int)retval);
+ return retval;
+}
+
+ssize_t led_write(struct file *fildes, const char __user *buff,size_t count, loff_t *offp){
+ struct led_dev *ldev = fildes->private_data;
+ u16 data=0;
+ ssize_t retval = 0;
+
+
+ PDEBUG("write : offset %d, count %d\n",(int)*offp,(int)count);
+ if(down_interruptible(&ldev->sem))
+ return -ERESTARTSYS;
+ if(*offp != 0){ /* offset must be 0 */
+ goto out;
+ }
+ if(count != 1) /* Only one word can be read */
+ count = 1;
+
+ if(copy_from_user(&data,buff,1)){
+ printk(KERN_WARNING "write : copy from user error\n");
+ retval = -EFAULT;
+ goto out;
+ }
+
+ if((retval=led_fpga_write(ldev->fpga_virtual_base_address + FPGA_LED,&data,ldev))<0){
+ goto out;
+ }
+
+out:
+ up(&ldev->sem);
+ return retval;
+
+}
+
+int led_open(struct inode *inode, struct file *filp){
+ /* Allocate and fill any data structure to be put in filp->private_data */
+ filp->private_data = container_of(inode->i_cdev,struct led_dev, cdev);
+ PDEBUG( "Led opened\n");
+ return 0;
+}
+
+/* ******************************
+ * Init and release functions
+ * ******************************/
+int led_release(struct inode *inode, struct file *filp){
+ PDEBUG( "Led released\n");
+ return 0;
+}
+
+/**********************************
+ * Module management
+ **********************************/
+static int __init led_init(void){
+
+ int result; /* error return */
+ int led_major,led_minor;
+ u16 data;
+ struct led_dev *sdev;
+
+ led_major = 253;
+ led_minor = 0;
+
+ /* Allocate a private structure and reference it as driver's data */
+ PDEBUG("Allocate a private structure and reference it as driver s data\n");
+ sdev = (struct led_dev *)kmalloc(sizeof(struct led_dev),GFP_KERNEL);
+ if(sdev == NULL){
+ printk(KERN_WARNING "LED: unable to allocate private structure\n");
+ return -ENOMEM;
+ }
+
+ /* initiate mutex for accessing led */
+ PDEBUG("initiate mutex for accessing led\n");
+ init_MUTEX(&sdev->sem);
+
+ /* Get the major and minor device numbers */
+ PDEBUG("Get the major and minor device numbers\n");
+ if(led_major){
+ devno = MKDEV(led_major,led_minor);
+ result = register_chrdev_region(devno, N_DEV,LED_NAME);
+ }else{
+ result = alloc_chrdev_region(&devno,led_minor,N_DEV,LED_NAME);
+ led_major = MAJOR(devno);
+ }
+ printk(KERN_INFO "LED: MAJOR: %d MINOR: %d\n",MAJOR(devno),MINOR(devno));
+ if(result < 0){
+ printk(KERN_WARNING "LED: can't get major %d\n",led_major);
+ }
+
+ /* Init the cdev structure */
+ PDEBUG("Init the cdev structure\n");
+ cdev_init(&sdev->cdev,&led_fops);
+ sdev->cdev.owner = THIS_MODULE;
+
+ /* Add the device to the kernel, connecting cdev to major/minor number */
+ PDEBUG("Add the device to the kernel, connecting cdev to major/minor number \n");
+ result = cdev_add(&sdev->cdev,devno,1);
+ if(result < 0)printk(KERN_WARNING "LED: can't add cdev\n");
+
+ sdev->fpga_virtual_base_address = (void*)IMX_CS1_VIRT;
+
+ /* initialyzing sysfs */
+ PDEBUG(" initialyzing sysfs\n");
+ if(unlikely(result = init_sysinterface(sdev)))
+ goto error;
+
+ /* initialize led value */
+ data=1;
+ if((result=led_fpga_write(sdev->fpga_virtual_base_address + FPGA_LED,&data,sdev))<0)
+ goto error;
+
+ sdev->previousint = jiffies;
+ /* OK module inserted ! */
+ leddev=sdev;
+ printk(KERN_INFO "Led module insered\n");
+ return 0;
+
+error:
+ printk(KERN_ERR "%s: not inserted\n",LED_NAME);
+ free_all();
+ return result;
+}
+
+static void __exit led_exit(void){
+ free_all();
+}
+
+static void free_all(void){
+ struct led_dev *sdev;
+ sdev = leddev;
+
+ /* unregister kobj */
+ kobject_unregister(&sdev->kobj);
+
+ /* delete the cdev structure */
+ cdev_del(&sdev->cdev);
+
+ /* Free the allocated memory */
+ kfree(sdev);
+
+ /* Release I/O memories */
+ release_mem_region(FPGA_BASE_ADDR,FPGA_MEM_SIZE);
+
+ /* free major and minor number */
+ unregister_chrdev_region(devno,N_DEV);
+ printk(KERN_INFO "Led module deleted\n");
+}
+
+module_init(led_init);
+module_exit(led_exit);
Added: trunk/target/linux/modules/fpga/Wb_led/led.h
===================================================================
--- trunk/target/linux/modules/fpga/Wb_led/led.h (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_led/led.h 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,123 @@
+/* led.h
+ * Driver for bus_led IP
+ * Fabien Marteau <fab...@ar...>
+ */
+
+
+#ifndef __LED_H__
+#define __LED_H__
+
+#include <linux/version.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+#include <linux/config.h>
+#endif
+
+/* specific header generated by orchestra */
+#include "led_specific.h"
+
+/* form module/drivers */
+#include <linux/init.h>
+#include <linux/module.h>
+
+/* linux device model */
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/sysdev.h>
+#include <linux/device.h>
+
+/* for file operations */
+#include <linux/fs.h>
+#include <linux/cdev.h>
+
+/* copy_to_user function */
+#include <asm/uaccess.h>
+
+/* request_mem_region */
+#include <linux/ioport.h>
+
+/* readw() writew() */
+#include <asm/io.h>
+
+/* hardware addresses */
+#include <asm/hardware.h>
+
+#endif
+
+/* for debugging messages*/
+#define LED_DEBUG
+
+#undef PDEBUG
+#ifdef LED_DEBUG
+# ifdef __KERNEL__
+ /* for kernel spage */
+# define PDEBUG(fmt,args...) printk(KERN_DEBUG "led : " fmt, ##args)
+# else
+ /* for user space */
+# define PDEBUG(fmt,args...) printk(stderr, fmt, ##args)
+# endif
+#else
+# define PDEBUG(fmt,args...) /* no debbuging message */
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Fabien Marteau <fab...@ar...> - ARMadeus Systems");
+MODULE_DESCRIPTION("Led device driver");
+
+/* major and minor number */
+#define N_DEV 1
+
+/* main device structure */
+struct led_dev{
+ struct cdev cdev; /* Char device structure */
+ struct semaphore sem; /* Mutex */
+ struct kobject kobj; /* kobject for sysfs entry */
+ void * fpga_virtual_base_address; /* fpga register base address*/
+ unsigned long previousint; /* last interruption time */
+};
+
+static void kobj_release(struct kobject *);
+static dev_t devno; /* to store Major and minor numbers */
+static struct led_dev *leddev;
+/* to read write led register */
+ssize_t led_read(struct file *fildes, char __user *buff,
+ size_t count, loff_t *offp);
+
+ssize_t led_write(struct file *fildes, const char __user *
+ buff,size_t count, loff_t *offp);
+int led_open(struct inode *inode, struct file *filp);
+
+int led_release(struct inode *, struct file *filp);
+
+struct file_operations led_fops = {
+ .owner = THIS_MODULE,
+ .read = led_read,
+ .write = led_write,
+ .open = led_open,
+ .release = led_release,
+};
+
+/* Sysfs operation */
+static struct attribute led_status_attr = {
+ .name = "status",
+ .owner = THIS_MODULE,
+ .mode = 0666,
+};
+
+static int init_sysinterface(struct led_dev *pdev);
+static ssize_t led_show_status(struct kobject *kobj,struct attribute *attr,char *buf);
+static ssize_t led_store_status(struct kobject *kobj,struct attribute *attr, const char *buff, size_t size);
+
+static struct sysfs_ops led_status_fs_ops = {
+ .show = led_show_status,
+ .store = led_store_status,
+};
+
+struct kobj_type kobjtype = {
+ .release = kobj_release,
+ .sysfs_ops = &led_status_fs_ops,
+};
+
+static void free_all(void);
+
+static ssize_t led_fpga_read(void * addr, u16 *data , struct led_dev *dev);
+static ssize_t led_fpga_write(void * addr, u16 *data, struct led_dev *dev);
Added: trunk/target/linux/modules/fpga/Wb_led/led.mod.c
===================================================================
--- trunk/target/linux/modules/fpga/Wb_led/led.mod.c (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_led/led.mod.c 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,21 @@
+#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 char __module_depends[]
+__attribute_used__
+__attribute__((section(".modinfo"))) =
+"depends=";
+
Added: trunk/target/linux/modules/fpga/Wb_led/led_specific.h
===================================================================
--- trunk/target/linux/modules/fpga/Wb_led/led_specific.h (rev 0)
+++ trunk/target/linux/modules/fpga/Wb_led/led_specific.h 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,12 @@
+/* this file as been generated by orchestra
+ * do not modify it manualy
+ */
+
+#define FPGA_LED 4
+#define FPGA_IRQ_MASK 0
+#define FPGA_IRQ_PEND 2
+#define FPGA_IRQ_ACK 2
+
+#define FPGA_BASE_ADDR IMX_CS1_PHYS
+#define FPGA_MEM_SIZE IMX_CS1_SIZE
+#define LED_NAME "led"
Added: trunk/target/linux/modules/fpga/fpga_devtools/Kconfig
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/Kconfig (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/Kconfig 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,9 @@
+#
+
+#
+config ARMADEUS_FPGA_TOOL_DRIVER
+ tristate "Armadeus FPGA configuration driver"
+ default n
+ depends on ARMADEUS_FPGA_DRIVERS
+ ---help---
+
Added: trunk/target/linux/modules/fpga/fpga_devtools/Makefile
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/Makefile (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/Makefile 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,36 @@
+#
+# Makefile for the Armadeus FPGA loader driver
+# PATH=$HOME/nico/test/buildroot/build_arm_nofpu/staging_dir/bin:$PATH
+# make ARCH=arm
+# tftp -gr fpgaloader.ko -l /lib/modules/drivers/fpgaloader.ko 192.168.0.3
+# tftp -gr fpga_test.bit 192.168.0.3
+# insmod /lib/modules/drivers/fpgaloader.ko
+# dd if=fpga_test.bit of=/dev/fpga/loader
+
+
+BASE_DIR="../../../../buildroot/"
+
+REL=`grep "BR2_PACKAGE_LINUX_VERSION=" $(BASE_DIR).config | \
+ sed "s/BR2_PACKAGE_LINUX_VERSION=\\"//" | sed "s/\\"//"`
+
+ARMADEUS_KERNEL_DIR=$(BASE_DIR)build_arm_nofpu/linux-$(REL)
+
+ifneq ($(KERNELRELEASE),)
+
+obj-$(CONFIG_ARMADEUS_FPGA_TOOL_DRIVER) += fpgaloader.o
+fpgaloader-objs := target-fpga-loader.o xilinx-fpga-loader.o fpga-loader.o
+
+else
+KDIR := $(ARMADEUS_KERNEL_DIR)
+PWD := $(shell pwd)
+
+default:
+ $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+
+clean:
+ rm -f *.*o \
+ rm -f Module.symvers
+
+
+endif
+
Added: trunk/target/linux/modules/fpga/fpga_devtools/fpga-loader.c
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/fpga-loader.c (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/fpga-loader.c 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,284 @@
+/*
+ ***********************************************************************
+ *
+ * (c) Copyright 2006 Armadeus project
+ * Julien Boibessot <jul...@ar...>
+ * Nicolas Colombain <nic...@ar...>
+ * Generic Xilinx FPGA loader
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ **********************************************************************
+ */
+#include <linux/version.h>
+#include "fpga-loader.h"
+#include "xilinx-fpga-loader.h"
+#include <asm/arch/imx-regs.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+//static unsigned long init_map;
+struct semaphore fpga_sema;
+
+/* global variables */
+static int fpga_major = FPGA_MAJOR;
+Xilinx_desc* g_current_desc = NULL;
+
+static unsigned char fpga_descriptor = 0; // use default target_fpga_desc
+module_param( fpga_descriptor, byte, 0 );
+
+#define FPGA_BUFFER_SIZE 4096
+static unsigned char g_buffer[FPGA_BUFFER_SIZE];
+static unsigned char g_nb_users = 0;
+
+
+void __exit armadeus_fpga_cleanup(void);
+
+
+//------------------------------------------------
+//
+// Handles write() done on /dev/fpgaxx
+//
+static ssize_t armadeus_fpga_write(struct file *file, const char* pData, size_t count, loff_t *f_pos)
+{
+ ssize_t ret = 0;
+
+ // Get exclusive access
+ if (down_interruptible(&fpga_sema))
+ return -ERESTARTSYS;
+
+ if( count > FPGA_BUFFER_SIZE ) {
+ count = FPGA_BUFFER_SIZE;
+ }
+
+ // Get value to write from user space
+ ret = __copy_from_user( g_buffer, pData, count);
+ if (ret != 0) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = xilinx_load( g_current_desc, g_buffer, count );
+
+out:
+ // Release exclusive access
+ up(&fpga_sema);
+
+ return( ret );
+}
+
+static int armadeus_fpga_open(struct inode *inode, struct file *file)
+{
+ int ret;
+
+ // Only one access at a time is permitted
+ if( g_nb_users > 0 )
+ return( -EBUSY );
+
+ g_nb_users++;
+ ret = xilinx_init_load( g_current_desc );
+
+ PRINTF("Opening /dev/fpga/loader%d file, %d %d\n", MINOR(inode->i_rdev), fpga_descriptor, ret);
+ return ret;
+}
+
+static int armadeus_fpga_release(struct inode *inode, struct file *file)
+{
+ if( g_nb_users > 0 )
+ g_nb_users--;
+
+ PRINTF("Closing access to /dev/fpga/loader%d\n", MINOR(inode->i_rdev));
+ return 0;
+}
+
+//------------------------------------------------
+// PROC file
+//
+static int procfile_fpga_read( char *buffer, __attribute__ ((unused)) char **start, off_t offset, int buffer_length, int *eof, __attribute__ ((unused)) void* data)
+{
+ int ret;
+
+ // We give all of our information in one go, so if the user asks us if we have more information the answer should always be no.
+ // This is important because the standard read function from the library would continue to issue the read system call until
+ // the kernel replies that it has no more information, or until its buffer is filled.
+ if( offset > 0 ) {
+ /* we have finished to read, return 0 */
+ ret = 0;
+ } else {
+ if ( data == NULL ){
+ ret = xilinx_get_descriptor_info( -1, buffer );
+ }
+ else {
+ ret = xilinx_get_descriptor_info( *((unsigned char*)data), buffer );
+ }
+ }
+
+ return ret;
+}
+
+
+static int procfile_fpga_write( __attribute__ ((unused)) struct file *file, const char *buf, unsigned long count, void *data)
+{
+ return count;
+}
+
+//------------------------------------------------
+// Handling of IOCTL calls
+//
+int armadeus_fpga_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg )
+{
+ int err = 0; int ret = 0;
+ unsigned int minor;
+
+ PRINTF( DRIVER_NAME " ## IOCTL received: (0x%x) ##\n", cmd );
+
+ // Extract the type and number bitfields, and don't decode wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
+ if (_IOC_TYPE(cmd) != FPGA_IOCTL) return -ENOTTY;
+
+ // The direction is a bitmask, and VERIFY_WRITE catches R/W transfers. `Type' is user-oriented, while access_ok is kernel-oriented,
+ // so the concept of "read" and "write" is reversed
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
+
+ if (err) return -EFAULT;
+
+ // Obtain exclusive access
+ if (down_interruptible(&fpga_sema))
+ return -ERESTARTSYS;
+ // Extract and test minor
+ minor = MINOR(inode->i_rdev);
+ if( minor > FPGA_MAX_MINOR ) {
+ printk("Minor outside range: %d !\n", minor);
+ return -EFAULT;
+ }
+
+ switch(cmd)
+ {
+ default:
+ return -ENOTTY;
+ break;
+ }
+ // Release exclusive access
+ up(&fpga_sema);
+
+ return ret;
+}
+
+//
+// Create /proc entries for direct access (with echo/cat) to GPIOs config
+//
+static int createProcEntries( void )
+{
+ static struct proc_dir_entry *fpga_Proc_File;
+
+ // Create main directory
+ proc_mkdir(FPGA_PROC_DIRNAME, NULL);
+ // Create proc file to handle GPIO values
+ fpga_Proc_File = create_proc_entry( FPGA_PROC_FILENAME, S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH, NULL );
+
+ if( fpga_Proc_File == NULL )
+ {
+ printk(FPGA_DRIVER_NAME ": Could not register a" FPGA_PROC_FILENAME ". Terminating\n");
+ armadeus_fpga_cleanup();
+ return -ENOMEM;
+ }
+ else
+ {
+ fpga_Proc_File->read_proc = procfile_fpga_read;
+ fpga_Proc_File->write_proc = procfile_fpga_write;
+ }
+
+ return(0);
+}
+
+static struct file_operations fpga_fops = {
+ .owner = THIS_MODULE,
+ .write = armadeus_fpga_write,
+// .read = armadeus_fpga_read,
+ .open = armadeus_fpga_open,
+ .release = armadeus_fpga_release,
+ .ioctl = armadeus_fpga_ioctl,
+};
+
+//
+// Module's initialization function
+//
+int __init armadeus_fpga_init(void)
+{
+ static int result;
+
+ // Register the driver by getting a major number
+ result = register_chrdev(fpga_major, FPGA_DRIVER_NAME, &fpga_fops);
+ if (result < 0)
+ {
+ printk(KERN_WARNING FPGA_DRIVER_NAME ": can't get major %d\n", fpga_major);
+ return result;
+ }
+ if( fpga_major == 0 ) fpga_major = result; // dynamic Major allocation
+
+ // Creating /proc entries
+ result = createProcEntries();
+ if( result < 0 ) return( result );
+
+ // Initialise FPGA semaphore
+ sema_init(&fpga_sema, 1);
+
+ // initialize the current fpga descriptor with the one by default
+ g_current_desc = xilinx_get_descriptor(fpga_descriptor);
+ if( g_current_desc == NULL ){
+ return -EINVAL;
+ }
+
+ printk(FPGA_DRIVER_NAME " module " FPGA_DRIVER_VERSION " successfully loaded !\n");
+ return(0);
+}
+
+//
+// Module's cleanup function
+//
+void __exit armadeus_fpga_cleanup(void)
+{
+ PRINTF("Removing " FPGA_DRIVER_NAME " module: ");
+
+ // Remove /proc entries
+ remove_proc_entry(FPGA_PROC_FILENAME, NULL);
+ // De-register /dev interface
+ unregister_chrdev(fpga_major, FPGA_DRIVER_NAME);
+
+ PRINTF("Ok !\n ");
+}
+
+//------------------------------------------------
+
+module_init(armadeus_fpga_init);
+module_exit(armadeus_fpga_cleanup);
+
+MODULE_AUTHOR("JB / NC");
+MODULE_DESCRIPTION("Armadeus fpga's loading driver");
+MODULE_LICENSE("GPL");
Added: trunk/target/linux/modules/fpga/fpga_devtools/fpga-loader.h
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/fpga-loader.h (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/fpga-loader.h 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,40 @@
+/*
+ ***********************************************************************
+ *
+ * (c) Copyright 2006 Armadeus project
+ * Julien Boibessot <jul...@ar...>
+ * Nicolas Colombain <nic...@ar...>
+ * Generic Xilinx FPGA loader
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ **********************************************************************
+ */
+
+#ifndef __FPGA_LOADER_H__
+#define __FPGA_LOADER_H__
+
+#define FPGA_PROC_DIRNAME "driver/fpga"
+#define FPGA_PROC_FILENAME FPGA_PROC_DIRNAME "/loader"
+
+#define FPGA_DRIVER_VERSION "v0.0.6"
+#define FPGA_DRIVER_NAME "fpgaloader"
+
+// By default, we use dynamic allocation of major numbers
+#define FPGA_MAJOR 0
+#define FPGA_MAX_MINOR 254
+
+#define FPGA_IOCTL 0x10000000 // !! TO BE BETTER DEFINED !!
+
+#endif // __FPGA_LOADER_H__
Added: trunk/target/linux/modules/fpga/fpga_devtools/fpgaloader.sh
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/fpgaloader.sh (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/fpgaloader.sh 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Load FPGA main module
+modprobe fpgaloader fpga_descriptor=0
+
+FPGA_MAJOR=`cat /proc/devices | grep fpgaloader | cut -d " " -f 1`
+mkdir -p /dev/fpga
+
+# For general usage
+if [ ! -e /dev/fpga/fpgaloader ] ; then
+ mknod /dev/fpga/fpgaloader c $FPGA_MAJOR 0
+fi
Added: trunk/target/linux/modules/fpga/fpga_devtools/target-fpga-loader.c
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/target-fpga-loader.c (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/target-fpga-loader.c 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,116 @@
+/*
+ **********************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ **********************************************************************
+
+ (c) Copyright 2006 Armadeus project
+ Eric Jarrige <eri...@ar...>
+ Nicolas Colombain <nic...@ar...>
+ Target Xilinx FPGA support
+*/
+
+#include "target-fpga-loader.h"
+#include "xilinx-fpga-loader.h"
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+#define GPIO_PORT(x) ((x >> 5) & 3)
+#define GPIO_SET(x) (DR(GPIO_PORT(x)) |= (1<<(x & GPIO_PIN_MASK)))
+#define GPIO_CLEAR(x) (DR(GPIO_PORT(x)) &= ~(1<<(x & GPIO_PIN_MASK)))
+#define GPIO_WRITE(x,y) ( y ? GPIO_SET(x) : GPIO_CLEAR(x) )
+#define GPIO_READ(x) ((SSR (GPIO_PORT(x)) & (1<<(x & GPIO_PIN_MASK))))
+
+/*
+ * Set the FPGA's active-low program line to the specified level
+ */
+int fpga_pgm_fn( int assert )
+{
+ GPIO_WRITE( FPGA_PROGRAM, !assert);
+ return assert;
+}
+
+/*
+ * Set the FPGA's active-high clock line to the specified level
+ */
+int fpga_clk_fn( int assert_clk )
+{
+ GPIO_WRITE( FPGA_CLOCK, assert_clk);
+ return assert_clk;
+}
+
+/*
+ * Test the state of the active-low FPGA INIT line. Return 1 on INIT
+ * asserted (low).
+ */
+int fpga_init_fn( void )
+{
+ return(!GPIO_READ(FPGA_INIT));
+}
+
+/*
+ * Test the state of the active-high FPGA DONE pin
+ */
+int fpga_done_fn( void )
+{
+ return(GPIO_READ(FPGA_DONE));
+}
+
+/*
+ * Set the FPGA's data line to the specified level
+ */
+int fpga_wr_fn( int assert_write )
+{
+ GPIO_WRITE( FPGA_DIN, assert_write);
+ return assert_write;
+}
+
+int fpga_pre_fn( void )
+{
+ // Initialize GPIO pins
+ imx_gpio_mode (FPGA_INIT | GPIO_GIUS | GPIO_DR | GPIO_IN );
+ imx_gpio_mode (FPGA_DONE | GPIO_GIUS | GPIO_DR | GPIO_IN );
+ imx_gpio_mode (FPGA_DIN | GPIO_GIUS | GPIO_DR | GPIO_OUT );
+ imx_gpio_mode (FPGA_PROGRAM | GPIO_GIUS | GPIO_DR | GPIO_OUT );
+ imx_gpio_mode (FPGA_CLOCK | GPIO_GIUS | GPIO_DR | GPIO_OUT );
+ return 1;
+}
+
+
+Xilinx_Spartan_Slave_Serial_fns fpga_fns = {
+ fpga_pre_fn,
+ fpga_pgm_fn,
+ fpga_clk_fn,
+ fpga_init_fn,
+ fpga_done_fn,
+ fpga_wr_fn,
+};
+
+Xilinx_desc target_fpga_desc[NB_TARGET_DESC] = {
+
+ { // first supported configuration (default)
+ Xilinx_Spartan,
+ slave_serial,
+ XILINX_XC3S200_SIZE,
+ (void *) &fpga_fns
+ },
+
+ { // second one
+ Xilinx_Spartan,
+ slave_serial,
+ XILINX_XC3S400_SIZE,
+ (void *) &fpga_fns
+ }
+};
+
Added: trunk/target/linux/modules/fpga/fpga_devtools/target-fpga-loader.h
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/target-fpga-loader.h (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/target-fpga-loader.h 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,40 @@
+/*
+ **********************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ **********************************************************************
+
+ (c) Copyright 2006 Armadeus project
+ Eric Jarrige <eri...@ar...>
+ Nicolas Colombain <nic...@ar...>
+ Target Xilinx FPGA support
+
+*/
+#ifndef __TARGET_FPGA_LOADER_H__
+#define __TARGET_FPGA_LOADER_H__
+
+
+#include "xilinx-fpga-loader.h"
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+
+#define FPGA_INIT (GPIO_PORTB | 15) /* FPGA init pin (SSI input) */
+#define FPGA_DONE (GPIO_PORTB | 16) /* FPGA done pin (SSI input) */
+#define FPGA_DIN (GPIO_PORTB | 17) /* FPGA data pin (SSI output) */
+#define FPGA_PROGRAM (GPIO_PORTB | 18) /* FPGA prog pin (SSI output) */
+#define FPGA_CLOCK (GPIO_PORTB | 19) /* FPGA clk pin (SSI output) */
+
+#define NB_TARGET_DESC 2
+
+#endif // __TARGET_FPGA_LOADER_H__
Added: trunk/target/linux/modules/fpga/fpga_devtools/xilinx-fpga-loader.c
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/xilinx-fpga-loader.c (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/xilinx-fpga-loader.c 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,277 @@
+/*
+ * (c) Copyright 2006 Armadeus project
+ * Nicolas Colombain <nic...@ar...>
+ * Xilinx FPGA support
+ *
+ * Based on the implementation(uBoot) of:
+ * Rich Ireland, Enterasys Networks, rir...@en....
+ * Keith Outwater, kei...@mv...
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include "xilinx-fpga-loader.h"
+#include "target-fpga-loader.h"
+#include <asm/arch/imx-regs.h>
+#include <asm/io.h>
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#define CONFIG_FPGA_DELAY()
+#define CFG_FPGA_WAIT 4000 // uS
+
+size_t bytecount = 0; // total bytes received
+extern Xilinx_desc target_fpga_desc[]; // target descriptor table
+
+/*
+ * Timeout function
+ */
+static unsigned long get_timer(unsigned long initTime)
+{
+ struct timeval tv;
+ do_gettimeofday(&tv);
+ if( tv.tv_usec > initTime ) // avoid overflow pb
+ return tv.tv_usec - initTime;
+ else
+ return initTime - tv.tv_usec;
+}
+
+/*
+ * dump the given descriptor infos
+ */
+static int xilinx_dump_descriptor_info( Xilinx_desc *desc, char* buffer )
+{
+ int len;
+ len = sprintf( buffer, "%s %s %u\n",
+ (desc->family == Xilinx_Spartan) ? "spartan":"unknown",
+ (desc->iface == slave_serial) ? "slave serial":"unknown",
+ desc->size );
+ return len;
+}
+
+/**
+ * program the FPGA.
+ * return 0 if success, >0 while programming, <0 if error detected
+ */
+static size_t spartan_serial_load (Xilinx_desc *desc, const char* buf, size_t bsize)
+{
+ Xilinx_Spartan_Slave_Serial_fns *fn = desc->iface_fns;
+ if (fn) {
+ unsigned long ts; /* timestamp */
+
+ /* Load the data */
+ if( bytecount<=desc->size ) {
+ int i;
+ unsigned char val;
+ size_t nbbyte = 0; // init local counter
+
+ while (nbbyte < bsize) {
+
+ /* Xilinx detects an error if INIT goes low (active)
+ while DONE is low (inactive) */
+ if ((*fn->done)() == 0 && (*fn->init)()) {
+ PRINTF ("** CRC error during FPGA load.\n");
+ return -ETIMEDOUT;
+ }
+ val = buf[nbbyte ++];
+ bytecount++;
+ i = 8;
+ do {
+ /* Deassert the clock */
+ (*fn->clk)(0);
+ CONFIG_FPGA_DELAY ();
+ /* Write data */
+ (*fn->wr)(val & 0x80);
+ CONFIG_FPGA_DELAY ();
+ /* Assert the clock */
+ (*fn->clk)(1);
+ CONFIG_FPGA_DELAY ();
+ val <<= 1;
+ i --;
+ } while (i > 0);
+ }
+ }
+ if( bytecount>=desc->size )
+ {
+ CONFIG_FPGA_DELAY ();
+
+ /* now check for done signal */
+ ts = get_timer(0); /* get current time */
+ (*fn->wr)(1);
+
+ while (! (*fn->done)()) {
+ CONFIG_FPGA_DELAY ();
+ (*fn->clk)(0); /* Deassert the clock pin */
+ CONFIG_FPGA_DELAY ();
+ (*fn->clk)(1); /* Assert the clock pin */
+
+ if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */
+ PRINTF ("** Timeout waiting for DONE.\n");
+ return -ETIMEDOUT;
+ }
+ }
+ }
+ return bsize;
+ }
+ return -EINVAL;
+}
+
+/**
+ * initialize the FPGA programming interface.
+ * return 0 if success, <0 if error detected
+ */
+static int spartan_serial_init (Xilinx_desc *desc)
+{
+ Xilinx_Spartan_Slave_Serial_fns *fn = desc->iface_fns;
+ if (fn) {
+ unsigned long ts; /* timestamp */
+
+ if(*fn->pre){
+ (*fn->pre)(); //Run the pre configuration function if there is one.
+ }
+
+ /* Establish the initial state */
+ (*fn->pgm)(1); /* Assert the program, commit */
+
+ /* Wait for INIT state (init low) */
+ ts = get_timer(0); /* get current time */
+ do {
+ CONFIG_FPGA_DELAY ();
+ if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */
+ PRINTF ("** Timeout waiting for INIT to start.\n");
+ return -ETIMEDOUT;
+ }
+ } while (!(*fn->init)());
+
+ /* Get ready for the burn */
+ CONFIG_FPGA_DELAY ();
+ (*fn->pgm)(0); /* Deassert the program, commit */
+
+ ts = get_timer(0); /* get current time */
+ /* Now wait for INIT to go high */
+ do {
+ CONFIG_FPGA_DELAY ();
+ if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */
+ PRINTF ("** Timeout waiting for INIT to clear.\n");
+ return -ETIMEDOUT;
+ }
+ } while ((*fn->init)());
+
+ bytecount = 0; // reset byte count
+ return 0; // success
+ }
+ return -EINVAL;
+}
+
+/**
+ * program the FPGA.
+ * return 0 if success, >0 while programming, <0 if error detected
+ */
+size_t xilinx_load( Xilinx_desc *desc, const char *buf, size_t bsize )
+{
+ int ret = 0;
+
+ if( desc ) {
+ switch( desc->family ) // check family
+ {
+ case Xilinx_Spartan:
+ {
+ switch( desc->iface ) // check donwload hardware interface
+ {
+ case slave_serial: ret = spartan_serial_load( desc, buf, bsize ); break;
+ default: PRINTF("interface not supported!\n"); ret = -ENOSYS; break;
+ }
+ }
+ break;
+ default: PRINTF("family not supported!\n"); ret = -ENOSYS; break;
+ }
+ }
+ else {
+ PRINTF("invalid FPGA descriptor!\n");
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+/**
+ * initialize the FPGA programming interface.
+ * return 0 if success, <0 if error detected
+ */
+int xilinx_init_load( Xilinx_desc *desc )
+{
+ int ret = 0;
+
+ if( desc ) {
+ switch( desc->family ) // check family
+ {
+ case Xilinx_Spartan:
+ {
+ switch( desc->iface ) // check donwload hardware interface
+ {
+ case slave_serial: ret = spartan_serial_init( desc ); break;
+ default: PRINTF("interface not supported!\n"); ret = -ENOSYS; break;
+ }
+ }
+ break;
+ default: PRINTF("family not supported!\n"); ret = -ENOSYS; break;
+ }
+ }
+ else {
+ PRINTF("invalid FPGA descriptor!\n");
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+/**
+ * get the descriptor corresponding to desc_id
+ * return NULL if error
+ */
+Xilinx_desc * xilinx_get_descriptor( unsigned char desc_id )
+{
+ if( desc_id < NB_TARGET_DESC ){
+ return &(target_fpga_desc[desc_id]);
+ }
+ return NULL;
+}
+
+/**
+ * get the descriptor infos
+ */
+int xilinx_get_descriptor_info( int desc_id, char* buffer )
+{
+ int len = 0;
+
+ if( desc_id >= 0 ) {
+ len = xilinx_dump_descriptor_info( &target_fpga_desc[desc_id], buffer );
+ }
+ else { // all desc requested
+ unsigned char i;
+ for( i=0; i<NB_TARGET_DESC; i++ ) {
+ len += xilinx_dump_descriptor_info( &target_fpga_desc[i], buffer+len );
+ }
+ }
+
+ return len;
+}
+
+
+
Added: trunk/target/linux/modules/fpga/fpga_devtools/xilinx-fpga-loader.h
===================================================================
--- trunk/target/linux/modules/fpga/fpga_devtools/xilinx-fpga-loader.h (rev 0)
+++ trunk/target/linux/modules/fpga/fpga_devtools/xilinx-fpga-loader.h 2008-04-02 08:00:54 UTC (rev 780)
@@ -0,0 +1,117 @@
+/*
+ * (c) Copyright 2006 Armadeus project
+ * Nicolas Colombain <nic...@ar...>
+ * Xilinx FPGA support
+ *
+ * Based on the implementation(uBoot) of:
+ * Rich Ireland, Enterasys Networks, rir...@en....
+ * Keith Outwater, kei...@mv...
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#ifndef __XILINX_FPGA_H__
+#define __XILINX_FPGA_H__
+
+#include <linux/types.h>
+
+//#define FPGA_DEBUG
+#undef FPGA_DEBUG
+
+#ifdef FPGA_DEBUG
+#define PRINTF(fmt,args...) printk (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+
+
+/* Spartan-III */
+#define XILINX_XC3S50_SIZE 439264/8
+#define XILINX_XC3S200_SIZE 1047616/8
+#define XILINX_XC3S400_SIZE 1699136/8
+#define XILINX_XC3S1000_SIZE 3223488/8
+#define XIL...
[truncated message content] |