📄 pwm.c
字号:
/*
* 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
*
* Copyright (C) 2002 Freescale Semiconductors HK Ltd
*
*/
/******************************************************************************
* Copyright (C) 2001, All Rights Reserved
*
* File Name: pwm.c
*
*
* Date of Creations: Mar 6, 2004
*
* Synopsis:
*
* Descirption:
* Driver for the DB-MX2 PWM, original from driver source for DB-MX1 PWM
*
* Modification History:
*
* ****************************************************************************/
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#define THOMAS_NO_SLEEP
#if 1
#include <linux/module.h>
#include <linux/version.h>
#endif
#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/miscdevice.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/timer.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 <linux/pm.h>
#include <asm/irq.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#include "pwm.h"
#define PWM_TEST
#undef ZHIMING_VERSION
// variables
int irq = 0;
int gWriteOk;
int gPwmMode;
char *gpWriteBuf;
U8 *gpWriteBufPtr8;
U16 *gpWriteBufPtr16;
int gWriteCnt;
int gDataLen;
U16 gSampleValue;
MODULE_PARM(irq, "i");
wait_queue_head_t ts_wait;
struct fasync_struct *ts_fasync;
int gMajor = 0; /* TODO dynamic major for now */
struct file_operations ts_fops = {
open: pwm_open,
release: pwm_release,
read: pwm_read,
write: pwm_write,
ioctl: pwm_ioctl,
fasync: pwm_fasync
};
// -----------------------
// FUNCTION ROUTINES
// -----------------------
//delay for a while
void delay (void)
{
U32 i=0;
for (i=0; i<10000; i++);
}
//software reset
void soft_reset (void)
{
int i;
//enable the PWM
_reg_PWM_PWMC |= 0x00000010;
// set SWR bit to 1
_reg_PWM_PWMC |= 0x00010000;
//disable the PWM
_reg_PWM_PWMC &= ~0x00000010;
//delay because PWM released after 5 system clock
for(i=0;i<5;i++)
delay ();
}
/******************************************************************************
* Function Name: pwm_release
*
* Input: inode :
* filp :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: release resource when close the inode
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
int pwm_release(struct inode * inode, struct file * filp)
{
PK("<1>in pwm_release ----\n");
// wait unit gWriteCnt == 0
interruptible_sleep_on(&ts_wait);
MOD_DEC_USE_COUNT;
PK("<1>out pwm_release ----\n");
return 0;
}
/******************************************************************************
* Function Name: pwm_open
*
* Input: inode :
* filp :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: allocate resource when open the inode
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
int pwm_open(struct inode * inode, struct file * filp)
{
PK("<1>in pwm_open ----\n");
MOD_INC_USE_COUNT;
// Init PWM hardware
initpwm();
gWriteOk = 0;
PK("<1>out pwm_open ----\n");
return 0;
}
/******************************************************************************
* Function Name: pwm_fasync
*
* Input: fd :
* filp :
* mode :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: provide fasync functionality for select system call
*
* Modification History:
*****************************************************************************/
static int pwm_fasync(int fd, struct file *filp, int mode)
{
PK("<1>in pwm_fasyn ----\n");
#if 0
/* TODO TODO put this data into file private data */
int minor = checkDevice( filp->f_dentry->d_inode);
if ( minor == - 1)
{
PK("<1>asp_fasyn:bad device minor\n");
return -ENODEV;
}
return( fasync_helper(fd, filp, mode, &ts_fasync) );
#endif
return 0;
}
/******************************************************************************
* Function Name: pwm_ioctl
*
* Input: inode :
* filp :
* cmd : command for ioctl
* arg : parameter for command
* Value Returned: int : Return status.If no error, return 0.
*
* Description: ioctl for this device driver
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
int pwm_ioctl(struct inode * inode,
struct file *filp,
unsigned int cmd ,
unsigned long arg)
{
char *str=NULL;
int ret = 0;
PK("<1>in pwm_ioctl ----\n");
switch(cmd)
{
case PWM_IOC_SMODE:
gPwmMode = arg;
if (gPwmMode == PWM_TONE_MODE)
{
// create periodic timer when tone mode
PK("PWM Tone Mode.\n");
pwmTimer.timer_blk_ptr = &timer_blk;
pwmTimer.timer_func = pwmIntFunc;
CreateTimer(&pwmTimer);
}
else
{
PK("PWM Play Mode.\n");
}
break;
case PWM_IOC_SFREQ:
_reg_PWM_PWMC &= ~0x00000010; // Disable PWM
_reg_PWM_PWMC &= 0xFFFF00F0; // sysclk
// check sampling rate
if (arg == PWM_SAMPLING_8KHZ)
{
// 96M / 23/2/256 = 8.152kHz
// _reg_PWM_PWMC |= (0 << 8); // pres = 22 (/23)
_reg_PWM_PWMC |= 0x00000900; // pres = 15 (/16) // 66M / 16/2/256 = 8.057KHZ
str = "8Khz";
}
else if (arg == PWM_SAMPLING_16KHZ)
{
_reg_PWM_PWMC |= (0 << 8); // pres = 11 (/12))
str = "16Khz";
}
_reg_PWM_PWMC &= ~0x3; // clksel = 0 (/2)
PK("<2>Sample rate = %s\n", str);
PK("<1>ioctl: PWMC = 0x%8x\n", _reg_PWM_PWMC);
break;
case PWM_IOC_SDATALEN:
gDataLen = arg;
if (arg == PWM_DATA_8BIT)
{
_reg_PWM_PWMP = 0xfe; // Period, 8bit
str = "8bit";
}
else // if(arg == PWM_DATA_16BIT)
{
_reg_PWM_PWMP = 0xfffe; // Period, 16bit
str = "16bit";
}
PK("<2>Data Length = %s\n", str);
break;
case PWM_IOC_SSAMPLE:
gSampleValue = arg;
break;
case PWM_IOC_SPERIOD:
if (gPwmMode == PWM_TONE_MODE)
{
PK("<1>PWM period = %d\n",(int)arg);
pwmTimer.period = arg/12;
}
break;
case PWM_IOC_STOP:
StopPwm();
break;
/*add--001begin*/
case PWM_IOC_SWAPDATA:
if (arg&PWM_SWAP_HCTRL) //Halfword FIFO data swapping
{
_reg_PWM_PWMC |= PWM_SWAP_HCTRL;
}
else
{
_reg_PWM_PWMC &= ~PWM_SWAP_HCTRL;
}
if (arg&PWM_SWAP_BCTRL) //Byte FIFO data swapping
{
_reg_PWM_PWMC |= PWM_SWAP_BCTRL;
}
else
{
_reg_PWM_PWMC &= ~PWM_SWAP_BCTRL;
}
break;
/*add--001end*/
default:
break;
}
PK("<1>out pwm_ioctl ----\n");
return ret;
}
/******************************************************************************
* Function Name: pwm_read
*
* Input: filp : the file
* buf : data buffer
* count : number of chars to be readed
* l : offset of file
* Value Returned: int : Return status.If no error, return 0.
*
* Description: read device driver
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
ssize_t pwm_read(struct file * filp, char * buf, size_t count, loff_t * l)
{
int ret;
PK("<1>in pwm_read ----\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -