⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pwm.c

📁 飞思卡尔的mx21处理器的pwm驱动程序源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -