📄 pwm.c
字号:
if(gWriteCnt == 0)
ret = 1; // no data
else
ret = 0; // processing data
PK("<1>out pwm_read ----\n");
return ret;
}
/******************************************************************************
* Function Name: pwm_interrupt
*
*
* Description: interrupt handler
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
void pwm_interrupt()
{
U16 tmp16;
U32 status;
PK("in pwm_interrupt ----\n");
// clear status
status = _reg_PWM_PWMC;
// check end
if(gWriteCnt < 0)
{
StopPwm();
return;
}
if (gPwmMode == PWM_PLAY_MODE)
{
if(gDataLen == PWM_DATA_8BIT)
{
_reg_PWM_PWMS = (U32)(*gpWriteBufPtr8++);
PK("<1>(%d) pwm_int: PWMS = 0x%8x\n", gWriteCnt, _reg_PWM_PWMS);
gWriteCnt--;
}
else if(gDataLen == PWM_DATA_16BIT)
{
tmp16 = *gpWriteBufPtr8++;
tmp16 |= (*gpWriteBufPtr8++ << 8);
_reg_PWM_PWMS = (U32)tmp16;
PK("<1>(%d) pwm_int: PWMS = 0x%8x\n", gWriteCnt, _reg_PWM_PWMS);
gWriteCnt -= 2;
}
}
PK("out pwm_interrupt ----\n");
}
static ssize_t pwm_write(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{
int ret = 0;
PK("<1>in pwm_write ----\n");
gWriteOk = 0;
gpWriteBuf = kmalloc(count, GFP_KERNEL);
if (!gpWriteBuf)
goto out;
gpWriteBufPtr8 = gpWriteBuf;
if (copy_from_user(gpWriteBuf, buf, count))
{
ret = -EFAULT;
goto out;
}
//write data to PWM
gWriteCnt = count;
PK("<1>pwm_write: count = %d\n", gWriteCnt);
//enable IRQEN, PW
_reg_PWM_PWMC |= 0x00000010;
_reg_PWM_PWMS = 0x00000000;
if(gPwmMode == PWM_PLAY_MODE)
{
// PK("before set IRQEN\n");
_reg_PWM_PWMC |= 0x00000040;
PK("PWMC1= 0x%08x\n", _reg_PWM_PWMC);
// _reg_PWM_PWMS = 0x00000000;
}
else
{
_reg_PWM_PWMS = gSampleValue;
_reg_PWM_PWMC |= 0x7f00; // set prescaler to 128
gpWriteBufPtr16 = (U16*)gpWriteBuf;
gWriteCnt /= 2; //input size is 8bit size, need /2 to get 16bit size
StartTimer(&pwmTimer);
}
PK("<1>pwm_write: PWMC = 0x%8x\n", _reg_PWM_PWMC);
out:
PK("<1>out pwm_write ----\n");
return ret;
}
/******************************************************************************
* Function Name: initpwm
*
* Input: :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: initialize PWM hardware
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
static int __init initpwm()
{
PK("<1>in initpwm ----\n");
// Init Port PE5 : PWMO
_reg_CRM_PCCR1 |= 0x10000000;
_reg_GPIO_DDIR(GPIOE) |= 0x00000020;
_reg_GPIO_GIUS(GPIOE) &= ~0x00000020;
_reg_GPIO_GPR(GPIOE) &= ~0x00000020;
PK("<1>out initpwm ----\n");
return 1;
}
/******************************************************************************
* Function Name: pwm_init
*
* Input: void :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: device driver initialization
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
static devfs_handle_t devfs_handle;
#ifdef MODULE
int init_module(void)
#else
int __init pwm_init(void)
#endif
{
int result;
printk("PWM driver version 0.2.0\n");
PK("<1>Init module\n");
/* register our character device */
result = devfs_register_chrdev(0, MOD_NAME, &ts_fops);
if ( result < 0 )
{
printk("pwm driver: Unable to register driver\n");
return -ENODEV;
}
devfs_handle = devfs_register(NULL, "pwm", DEVFS_FL_DEFAULT,
result, 0,
S_IFCHR | S_IRUSR | S_IWUSR,
&ts_fops, NULL);
if( gMajor == 0 )
{
gMajor = result;
printk("PWM major number = %d\n",gMajor);
}
PK("Request IRQs for PWM_INT.\n");
result = request_irq(AITC_PWM_INT,
pwm_interrupt,
SA_INTERRUPT,
DEV_IRQ_NAME,
DEV_IRQ_ID);
if (result)
{
PK("<1>cannot init major= %d irq=%d\n", gMajor, irq);
devfs_unregister_chrdev(gMajor, MOD_NAME);
devfs_unregister(devfs_handle);
return -1;
}
// init wait queue
init_waitqueue_head(&ts_wait);
// register power manager
pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, handle_pm_event);
// init
initpwm();
PK("<1>Init module Complete\n");
return 0;
}
/******************************************************************************
* Function Name: pwm_cleanup
*
* Input: void :
* Value Returned: void :
*
* Description: clean up and free all of resource for this MODULE
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
#ifdef MODULE
void cleanup_module(void)
#else
void __exit pwm_cleanup(void)
#endif
{
free_irq(AITC_PWM_INT, DEV_IRQ_ID);
devfs_unregister_chrdev(gMajor, MOD_NAME);
devfs_unregister(devfs_handle);
disable_irq(AITC_PWM_INT);
}
// --------------------------------------------------------------------
// local rutines
/******************************************************************************
* Function Name: checkDevice
*
* Input: inode :
* Value Returned: int : Return status.If no error, return 0.
*
* Description: verify if the inode is a correct inode
*
* Modification History:
* 10 DEC,2001,
*****************************************************************************/
static int checkDevice(struct inode *pInode)
{
int minor;
kdev_t dev = pInode->i_rdev;
if( MAJOR(dev) != gMajor)
{
PK("<1>checkDevice bad major = %d\n",MAJOR(dev) );
return -1;
}
minor = MINOR(dev);
if ( minor < MAX_ID )
return minor;
else
{
PK("<1>checkDevice bad minor = %d\n",minor );
return -1;
}
}
/* timer */
int CreateTimer(PWM_Timer_t *timer)
{
init_timer(timer->timer_blk_ptr);
timer->timer_blk_ptr->function = timer->timer_func;
return(0);
}
int StartTimer(PWM_Timer_t *timer)
{
timer->timer_blk_ptr->expires = jiffies + timer->period;
timer->stop_flag = 0;
add_timer((struct timer_list *)timer->timer_blk_ptr);
return(0);
}
int StopTimer(PWM_Timer_t *timer)
{
timer->stop_flag = 1;
del_timer_sync((struct timer_list *)timer->timer_blk_ptr);
return(0);
}
void pwmIntFunc()
{
U32 period;
PK("<1>pwm sam int\n");
if (gWriteCnt > 0)
{
PK("<1>PWMS = 0x%4x\n", (U16)_reg_PWM_PWMS);
// 96M/128/2/period
period = *gpWriteBufPtr16++;
if(period > 0)
// _reg_PWM_PWMP = 96000000/128/12/2/period; //96000000/128/2*11
_reg_PWM_PWMP = 66000000/128/2/period; //96000000/128/2*11
PK("<1>PWMP = 0x%4x\n", (U16)_reg_PWM_PWMP);
PK("<1>PWMCNT = 0x%4x\n", (U16)_reg_PWM_PWMCNT);
StartTimer(&pwmTimer);
gWriteCnt--;
}
else
StopPwm();
}
void StopPwm()
{
if(gpWriteBuf)
kfree(gpWriteBuf);
_reg_PWM_PWMC &= ~0x00000040; // disable IRQEN
_reg_PWM_PWMC &= ~0x00000010; // disable EN
gWriteOk = 1;
gWriteCnt = 0;
gDataLen = 0;
gSampleValue = 0;
if(gPwmMode == PWM_TONE_MODE)
StopTimer(&pwmTimer);
// can release PWM now
wake_up_interruptible(&ts_wait);
PK("<1>data completed.\n");
PK("<1>PWMC = 0x%8x\n", (U32)_reg_PWM_PWMC);
}
static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data)
{
switch(rqst)
{
case PM_SUSPEND:
PK("<1> PM suspend event received in PWM device.\n");
StopPwm();
break;
case PM_RESUME:
PK("<1> PM resume event received in PWM device.\n");
break;
default:
break;
}
return 0;
} /* handle_pm_event */
#ifndef MODULE
module_init(pwm_init);
module_exit(pwm_cleanup);
#endif
/* end of file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -