#define __KERNEL__
#define MODULE
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/uaccess.h> /* get_user,copy_to_user */
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
//include <linux/malloc.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/init.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <linux/tqueue.h>
#include <linux/wait.h>
#include <asm/irq.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#include <asm/atomic.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
#include <linux/ioctl.h>
#include "mx1_def.h"
#include "motor.h"
#define MOTOR_MAGIC 'k'
#define SET_PULSE _IOW(MOTOR_MAGIC, 1,int)
//#define SET_PULSE _IO(MOTOR_MAGIC, 1)
#define MOTOR_ON _IO(MOTOR_MAGIC, 2)
#define MOTOR_OFF _IO(MOTOR_MAGIC, 3)
#define MOTOR_SUSPEND _IO(MOTOR_MAGIC, 4)
#define MOTOR_RUSUME _IO(MOTOR_MAGIC, 5)
//#define SET_PULSE_PULSE 0x5149
void motor_do_tasklet (unsigned long arg);
volatile long new_count;
long old_count;
struct tasklet_struct motor_tasklet;
DECLARE_TASKLET (motor_tasklet, motor_do_tasklet, 0);
spinlock_t motor_lock = SPIN_LOCK_UNLOCKED;
unsigned int result;
volatile int flag = 0;
unsigned int sec, time;
static volatile int local_pulse = 0xdfff; //The max num of local_pulse is 65536
struct timeval tv1; //for debug
wait_queue_head_t ts_wait;
struct file_operations rtc_fops = {
open:rtc_open,
read:rtc_read,
poll: rtc_poll,
release:rtc_release,
ioctl:motor_ioctl,
};
int
rtc_open (struct inode *inode, struct file *filp)
{
MOD_INC_USE_COUNT;
enable_irq (18);
writebit (RTC_RTCCTL) |= 0xa0; //Enable RTC and select 32k for rtc input
writebit (RTC_RTCIENR)|= 0x200; //SET_PULSE the interrupt time is 0.128s
writebit (TIMER2_TCTL2)|= 0x6; //Timer2 select 'TIN' generate pulse //0x6
writebit (TIMER2_TPRER2) &= ~0xff; //SET_PULSE the prescaler of timer2 is 1
writebit (PWMC1) |= 0x10; //Enable the pwm
writebit (PWMP1) |= 0xffff; //Setup the period register for pwm mode
writebit (PWMC1) |= 0xac;//default pwm choose perclk1 for source-clk;non-interrupt update pwms
writebit (PWMS1) |= 0xdfff; //Setup the sample register for initial pulse-width
//enable_irq(34);
writebit (TIMER2_TCTL2) |= 0x1; //Enable the timer 2
return 0;
}
int
rtc_release (struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
writebit (PWMC1) |= 0x10000; //reset the pwm
writebit (PWMC1) &= ~0x10; //disable pwm
disable_irq (18);
return 0;
}
ssize_t rtc_read (struct file * filp, char *buf, size_t count, loff_t * l)
{
int retval;
if (copy_to_user (buf, &old_count, sizeof (long)))
{
retval = -EFAULT;
}
else
{
retval = 0;
}
return retval;
}
unsigned int
rtc_poll (struct file *filp, struct poll_table_struct *wait)
{
poll_wait (filp, &ts_wait, wait);
if (flag == 1)
{
flag = 0; //数据已经更新
return POLLIN | POLLRDNORM;
}
else
{
return 0; //数据没有更新
}
}
static void
set_motor_onoff (int to)
{
if (to)
{
writebit (PWMC1) |= 0x10;
writebit (PWMP1) |= 0xffff;
writebit (PWMC1) &= ~0xff00;
writebit (PWMC1) |= 0xac;
writebit (PWMS1) |= 0xdfff;
}
else
{
writebit (PWMC1) |= 0x10000;
writebit (PWMC1) &= ~0x10;
}
}
static void
set_motor_sspnd_rsume (int to)
{
if (to)
{
spin_lock_irq (&motor_lock);
writebit (PWMS1) = 65535;
spin_unlock_irq (&motor_lock);
}
else
{
spin_lock_irq (&motor_lock);
writebit (PWMS1) = local_pulse;
spin_unlock_irq (&motor_lock);
}
}
static int
motor_ioctl (struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
int data = 0;
int retval;
switch (cmd)
{
case MOTOR_OFF:
case MOTOR_ON:
set_motor_onoff ((cmd == MOTOR_ON) ? 1 : 0);
return 0;
case MOTOR_SUSPEND:
case MOTOR_RUSUME:
set_motor_sspnd_rsume ((cmd == MOTOR_SUSPEND) ? 1 : 0);
return 0;
case SET_PULSE:
if (copy_from_user (&data, (int *) arg, sizeof (int)))
return -EFAULT;
if (data > 65535 || data < 0)
return -EFAULT;
printk("<1>The second count is:%d\n",(int)data);
spin_lock_irq (&motor_lock);
local_pulse = data;
writebit (PWMS1) = data;
spin_unlock_irq (&motor_lock); // local_pulse
printk ("<1>The value of local_pulse is:%i\n", local_pulse);
return 0;
break;
default:
return -EINVAL;
}
return retval;
}
static void
rtc_irq_handle (int irq, void *dev_id, struct pt_regs *regs)
{
new_count = writebit (TIMER2_TCN2);
//new_count=writebit(PWMCNT1);
//new_count=writebit(PWMS1);
writebit (RTC_RTCCTL) &= ~0xa0; //Disable RTC
writebit (RTC_RTCISR) |= 0x200; //Clear the interrupt statu bit of sam1(0.128s)
//writebit(TIMER2_TCTL2)|=0x1000;//SET_PULSE the ReSET_PULSE bit of timer2
writebit (TIMER2_TCTL2) &= ~0x1; //Clear the enable bit of timer2
writebit (TIMER2_TCTL2) |= 0x6; //Re-SET_PULSE the clock-source of timer2
writebit (TIMER2_TPRER2) &= ~0xff; //Re-SET_PULSE the prescaler of timer2 is 1
//printk("<1>The second count is:%6i\n",(int)new_count);
tasklet_schedule (&motor_tasklet);
writebit (TIMER2_TCTL2)|= 0x1; //Enable the timer 2
writebit (RTC_RTCCTL) |= 0xa0; //Enable the rtc
//local_pulse=local_pulse2;//for debug
}
void
motor_do_tasklet (unsigned long arg)
{
flag = 1;
if(new_count<65535)
old_count = new_count;
else
old_count =65535;
//spin_lock_irq (&motor_lock);
// writebit (PWMS1) = (int)old_count;
//spin_unlock_irq (&motor_lock);
wake_up_interruptible (&ts_wait);
}
#ifdef MODULE
int
init_module (void)
#else /*
*/
int __init
init_rtc (void)
#endif /*
*/
{
init_waitqueue_head (&ts_wait);
writebit (PTA_GIUS) &= 0xfffffff9; //SET_PULSE port A[1] and A[2] for multix
writebit (PTA_GPR) &= 0xfffffff9; // SET_PULSE port A[1] and A[2] for primary function
writebit(PTD_GIUS)&=0x7fffffff;//Prepare to SET_PULSE the Timer2_out pin enable
//writebit(PTD_GPR)&=0x7fffffff;//..
result = register_chrdev (253, "motor", &rtc_fops);
if (result < 0)
{
unregister_chrdev (253, "motor");
return result;
}
result = request_irq (18, rtc_irq_handle, SA_SHIRQ, "rtc", dev_id); //SA_INTERRUPT
//result=request_irq(34,pwm_irq_handle,SA_INTERRUPT,"pwm", dev_id);
//disable_irq(34);
return 0;
}
#ifdef MODULE
void
cleanup_module (void)
#else /*
*/
void __exit
cleanup_rtc (void)
#endif /*
*/
{ //writebit(PWMC1)|=0x10000;//reSET_PULSE the pwm
writebit (RTC_RTCCTL) &= ~0x000000a0; //disable rtc
writebit (TIMER2_TCTL2) &= ~0x1; //disable timer2
writebit (PWMC1) &= ~0x10; //disable pwm
//writebit(PWMP1)&=0x0000;//for debug
//writebit(PWMS1)&=0x0000;//for debug clear the period bit of pwm
disable_irq (18);
free_irq (18, dev_id);
//disable_irq(34);
//free_irq(34, dev_id);
unregister_chrdev (253, "motor");
}
#ifndef MODULE
module_init (init_rtc);
module_exit (cleanup_rtc);
#endif
/*
static void pwm_irq_handle(int irq, void *dev_id, struct pt_regs *regs)
{ spin_lock_irq(&motor_lock);
//writebit(PWMS1)=local_pulse;
//writebit(PWMC1)|=0xef;
spin_unlock_irq(&motor_lock);//local_pulse
//do_gettimeofday(&tv1);