HPI driver source code

Source: Internet
Author: User

Author-------Dansen-----xzd2734@163.com

The source code I wrote is provided. Here, the interrupt and several variables are added to the catch-up task. They are basically not generic. You can continue to improve them, but they are used for the moment. The shared variables used in the interrupt are not protected. This is an error. At least stop the interrupt! Modified again!

/*
Dsp hpi interface with ARM 9 for S3C2410
Author -------- Dansen ---- 2007.09.05
*/

# Ifndef _ KERNEL __
# DEFINE _ KERNEL __
# Endif
# Ifndef Module
# Define Module
# Endif

# Include <Linux/config. h>
# Include <Linux/module. h>
# Include <Linux/kernel. h>/* printk ()*/
# Include <Linux/slab. h>/* kmalloc ()*/
# Include <Linux/ioport. h>
# Include <Linux/fs. h>/* everything ...*/
# Include <Linux/errno. h>/* error codes */
# Include <Linux/types. h>/* size_t */
# Include <Linux/proc_fs.h>
# Include <Linux/fcntl. h>/* o_accmode */
# Include <ASM/uaccess. h>
# Include <ASM/hardware. h>
# Include <ASM/IO. h>
# Include <ASM/IRQ. h>

// # Define hpi_debug
# UNDEF pdebug/* UNDEF it, just in case */
# Ifdef hpi_debug
# Ifdef _ KERNEL _/* this one if debugging is on, and kernel space */
# Define pdebug (FMT, argS...) printk (kern_emerg "HPI:" FMT, ## ARGs)
# Else/* this one for user space */
# Define pdebug (FMT, argS...) fprintf (stderr, FMT, # ARGs)
# Endif
# Else
# Define pdebug (FMT, argS...)/* Not debugging: nothing */
# Endif

# Define hpi_baseaddr 0x10000300 // bank 2

# Define hpi_major 200/* dynamic major by default */
# Define hpi_int irq_eint19

# Define hpi_magic 'K'
# Define hpi_reset _ IO (hpi_magic, 0)
# Define write_hpic _ IO (hpi_magic, 1)
# Define read_hpic _ IO (hpi_magic, 2)
# Define write_hpia _ IO (hpi_magic, 3)
# Define read_hpia _ IO (hpi_magic, 4)
# Define write_hpid_auto _ IO (hpi_magic, 5)
# Define read_hpid_auto _ IO (hpi_magic, 6)
# Define write_hpid _ IO (hpi_magic, 7)
# Define read_hpid _ IO (hpi_magic, 8)
# Define auto_hpid _ IO (hpi_magic, 9)
# Define noauto_hpid _ IO (hpi_magic, 10)
# Define set_dspint _ IO (hpi_magic, 11)
# Define get_ball_found _ IO (hpi_magic, 12)
# Define get_ball_cy _ IO (hpi_magic, 13)
# Define get_ball_cx _ IO (hpi_magic, 14)
# Define disable_int _ IO (hpi_magic, 15)
# Define enable_int _ IO (hpi_magic, 16)
# Define hpi_ioc_maxnr 16

Typedef struct hpi_device
{
Int no_autoread;
Int ball_found;
Int ball_cy;
Int ball_cx;
Unsigned int buzy;
Void * hpi_vbase;
Char * hpibasebufread;
Char * hpibasebufwrite;
Struct semaphore SEM;
} Hpi_dev;

Devfs_handle_t hpi_devfs;
Hpi_dev * hpi_dev;

Int hpi_open (struct inode * inode, struct file * filp)
{
Pdebug ("HPI device_open (% P, % P)/n", inode, filp );
If (hpi_dev-> buzy)
{
Printk ("HPI device is in using/N ");
Return-1;
}
Hpi_dev-> buzy = 1;
Filp-> private_data = hpi_dev;
Mod_inc_use_count;
Enable_irq (hpi_int );
Return 0;
}

Int hpi_release (struct inode * inode, struct file * filp)
{
Disable_irq (hpi_int );
Mod_dec_use_count;
Hpi_dev-> buzy = 0;
Pdebug ("HPI device_release (% P, % P)/n", inode, filp );
Return 0;
}

Inline void hpic_write (2010w)
{
Unsigned char T1, T2;
T1 = (0xff00 & W)> 8;
T2 = (0x00ff & W );
Outb (T1, hpi_dev-> hpi_vbase + 0x00 );
Outb (t2, hpi_dev-> hpi_vbase + 0x02 );
}

Inline 2010hpic_read (void)
{
Unsigned char T1, T2;
T1 = INB (hpi_dev-> hpi_vbase + 0x10 );
T2 = INB (hpi_dev-> hpi_vbase + 0x12 );
Return (t1 <8) | T2 );
}

Inline void hpia_write (2010w)
{
Unsigned char T1, T2;
T1 = (0xff00 & W)> 8;
T2 = (0x00ff & W );
Outb (T1, hpi_dev-> hpi_vbase + 0x04 );
Outb (t2, hpi_dev-> hpi_vbase + 0x06 );
}

Inline 2010hpia_read (void)
{
Unsigned char T1, T2;
T1 = INB (hpi_dev-> hpi_vbase + 0x14 );
T2 = INB (hpi_dev-> hpi_vbase + 0x16 );
Return (t1 <8) | T2 );
}

Inline void hpid_autowrite (2010w)
{
Unsigned char T1, T2;
T1 = (0xff00 & W)> 8;
T2 = (0x00ff & W );
Outb (T1, hpi_dev-> hpi_vbase + 0x08 );
Outb (t2, hpi_dev-> hpi_vbase + 0x0a );
}

Inline 2010hpid_autoread (void)
{
Unsigned char T1, T2;
T1 = INB (hpi_dev-> hpi_vbase + 0x18 );
T2 = INB (hpi_dev-> hpi_vbase + 0x1a );
Return (t1 <8) | T2 );
}

Inline void hpid_write (W)
{
Unsigned char T1, T2;
T1 = (0xff00 & W)> 8;
T2 = (0x00ff & W );
Outb (T1, hpi_dev-> hpi_vbase + 0x0c );
Outb (t2, hpi_dev-> hpi_vbase + 0x0e );
}

Inline 2010hpid_read (void)
{
Unsigned char T1, T2;
T1 = INB (hpi_dev-> hpi_vbase + 0x1c );
T2 = INB (hpi_dev-> hpi_vbase + 0x1e );
Return (t1 <8) | T2 );
}

Inline void setdspint (void)
{
Hpic_write (hpic_read () | 0x0404 );
}

Inline void clearhostint (void)
{
Hpic_write (hpic_read () | 0x0808 );
}

Static void hpi_interrupt (int irq, void * dev_id, struct pt_regs * regs)
{
Hpi_dev * Dev = dev_id;
Hpia_write (0x0000 );
Dev-> ball_found = hpid_autoread ();
Dev-> ball_cy = hpid_autoread ();
Dev-> ball_cx = hpid_autoread ();
}

Ssize_t hpi_read (struct file * filp, char * Buf, size_t count, loff_t * oppos)
{
Hpi_dev * Dev = filp-> private_data;
Int I;
Size_t ret;
If (Dev-> no_autoread) Count = 2;
Dev-> hpibasebufread = kmalloc (count, gfp_kernel );
If (! Dev-> hpibasebufread) Return-enomem;
If (down_interruptible (& Dev-> SEM ))
{
Kfree (Dev-> hpibasebufread );
Return-erestartsys;
}
For (I = 0; I <count/2; I ++)
{
If (Dev-> no_autoread)
(*) Dev-> hpibasebufread) [I] = hpid_read ();
Else
(*) Dev-> hpibasebufread) [I] = hpid_autoread ();
}
If (count % 2) (u8 *) Dev-> hpibasebufread) [count] = (u8) (hpid_autoread () & 0x00ff );
Ret = copy_to_user (BUF, Dev-> hpibasebufread, count )? -Efault: count;
Up (& (Dev-> SEM ));
Kfree (Dev-> hpibasebufread );
Return ret;
}

Ssize_t hpi_write (struct file * filp, const char * Buf, size_t count, loff_t * f_pos)
{
Hpi_dev * Dev = filp-> private_data;
Int I;
Size_t ret;
If (Dev-> no_autoread) Count = 2;
Dev-> hpibasebufwrite = kmalloc (count, gfp_kernel );
If (! Dev-> hpibasebufwrite) Return-enomem;
Down (& (Dev-> SEM ));
If (! Copy_from_user (Dev-> hpibasebufwrite, Buf, count ))
{
For (I = 0; I <count/2; I ++)
{
If (Dev-> no_autoread)
Hpid_write (002 *) Dev-> hpibasebufwrite) [I]);
Else
Hpid_autowrite (002 *) Dev-> hpibasebufwrite) [I]);
}
If (count % 2) hpid_autowrite (0000) (0 x | Dev-> hpibasebufwrite [count]);
Ret = count;
}
Else
Ret =-efault;
Up (& (Dev-> SEM ));
Kfree (Dev-> hpibasebufwrite );
Return ret;
}

Int hpi_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long Arg)
{
2010val;
Int ret;
Hpi_dev * Dev = filp-> private_data;
If (_ ioc_type (CMD )! = Hpi_magic) Return-enotty;
If (_ ioc_nr (CMD)> hpi_ioc_maxnr) Return-enotty;
Switch (CMD ){

Case hpi_reset:
Hpic_write (0x1818 );
Hpia_write (0x0003 );
Hpic_write (0x0808 );
Hpia_write (0x0000 );
Hpi_dev-> no_autoread = 0;
Break;

Case write_hpic:
Ret = get_user (Val, (2010*) Arg );
If (RET) return ret;
Hpic_write (VAL );
Break;

Case read_hpic:
Val = hpic_read ();
Return put_user (Val, (2010*) Arg );

Case write_hpia:
Ret = get_user (Val, (2010*) Arg );
If (RET) return ret;
Hpia_write (VAL );
Break;

Case read_hpia:
Val = hpia_read ();
Return put_user (Val, (2010*) Arg );

Case write_hpid_auto:
Ret = get_user (Val, (2010*) Arg );
If (RET) return ret;
Hpid_autowrite (VAL );
Break;

Case read_hpid_auto:
Val = hpid_autoread ();
Return put_user (Val, (2010*) Arg );

Case write_hpid:
Ret = get_user (Val, (2010*) Arg );
If (RET) return ret;
Hpid_write (VAL );
Break;

Case read_hpid:
Val = hpid_read ();
Return put_user (Val, (2010*) Arg );

Case auto_hpid:
Hpi_dev-> no_autoread = 0;
Break;

Case noauto_hpid:
Hpi_dev-> no_autoread = 1;
Break;

Case set_dspint:
Setdspint ();
Break;

Case get_ball_found:
Return put_user (Dev-> ball_found, (2010*) Arg );

Case get_ball_cy:
Return put_user (Dev-> ball_cy, (2010*) Arg );

Case get_ball_cx:
Return put_user (Dev-> ball_cx, (2010*) Arg );

Case disable_int:
Disable_irq (hpi_int );
Break;

Case enable_int:
Enable_irq (hpi_int );
Break;

Default:
Return-enotty;
}

Return 0;
}

Struct file_operations hpi_fops =
{
Open: hpi_open,
Release: hpi_release,
Read: hpi_read,
IOCTL: hpi_ioctl,
Write: hpi_write,
};

Int _ init hpi_init (void)
{
Pdebug ("hpi_init/N ");
Hpi_devfs = devfs_register (null, "HPI", devfs_fl_default, hpi_major, 0, s_ifchr | s_irusr | s_iwusr | s_irgrp | s_iwgrp, & hpi_fops, null );
If (null = hpi_devfs)
{
Printk ("HPI devfs_register failed/N ");
Goto fail_devfs_register;
}
Pdebug ("HPI devfs_register OK/N ");
Hpi_dev = kmalloc (sizeof (hpi_dev), gfp_kernel );
If (null = hpi_dev)
{
Printk ("fail_malloc hpi_dev/N ");
Goto fail_malloc;
}
Pdebug ("hpi_dev kmalloc OK/N ");
Memset (hpi_dev, 0, sizeof (hpi_dev ));
Sema_init (& hpi_dev-> SEM, 1 );
Hpi_dev-> no_autoread = 0;
Hpi_dev-> hpi_vbase = ioremap (hpi_baseaddr, 0x100 );
Pdebug ("hpi_dev-> hpi_vbase is % x/N", (unsigned INT) hpi_dev-> hpi_vbase );
If (null = request_region (unsigned INT) hpi_dev-> hpi_vbase, 0x100, "HPI "))
{
Printk ("HPI request_region failed/N ");
Goto fail_request_region;
}
Pdebug ("HPI request_region OK/N ");
Set_external_irq (hpi_int, ext_falling_edge, gpio_pullup_dis );
If (0! = Request_irq (hpi_int, & hpi_interrupt, sa_shirq, "HPI", hpi_dev ))
{
Printk ("HPI request_irq failed/N ");
Goto fail_request_irq;
}
Disable_irq (hpi_int );
Pdebug ("HPI request_irq OK/N ");
Return 0;
Fail_request_irq:
Release_region (unsigned INT) hpi_dev-> hpi_vbase, 0x100 );
Fail_request_region:
Iounmap (hpi_dev-> hpi_vbase );
Kfree (hpi_dev );
Fail_malloc:
Devfs_unregister (hpi_devfs );
Fail_devfs_register:
Return-1;
}

Void _ exit hpi_exit (void)
{
Pdebug ("HPI exit/N ");
Free_irq (hpi_int, hpi_dev );
Release_region (unsigned INT) hpi_dev-> hpi_vbase, 0x100 );
Iounmap (hpi_dev-> hpi_vbase );
Kfree (hpi_dev );
Pdebug ("HPI kfree OK/N ");
Devfs_unregister (hpi_devfs );
Pdebug ("HPI cleanup/N ");
}

Module_init (hpi_init );
Module_exit (hpi_exit );

Module_description ("dsp hpi driver ");
Module_author ("Dansen ");
Module_license ("GPL ");

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.