Mni2440 linux PWM driver code modification support frequency, duty cycle modification-XiaoLin. Peng

Source: Internet
Author: User

Author: Xiaolin. Peng

Welcome to discussion 196568501

# Include <Linux/module. h>
# Include <Linux/kernel. h>
# Include <Linux/fs. h>
# Include <Linux/init. h>
# Include <Linux/delay. h>
# Include <Linux/poll. h>
# Include <Linux/interrupt. h>
# Include <Linux/gpio. h>

# Include <ASM/IRQ. h>
# Include <ASM/IO. h>
# Include <ASM/uaccess. h>
# Include <Mach/regs-gpio.h>
# Include <Mach/hardware. h>
# Include <plat/regs-timer.h>
# Include <Mach/regs-irq.h>
# Include <ASM/Mach/time. h>
# Include <Linux/CLK. h>
# Include <Linux/cdev. h>
# Include <linux/device. h>
# Include <linux/miscdevice. h>

# Define DEVICE_NAME "pwm"

# Define PWM_IOCTL_SET_FREQ 1
# Define PWM_IOCTL_STOP 0

Static struct semaphore lock;

/* Freq: pclk/50/16/65536 ~ Pclk/50/16
* If pclk = 50 MHz, freq is 1Hz to 62500Hz
* Human ear: 20Hz ~ 20000Hz
*/
Static void PWM_Set_Freq_Duty (unsigned long freq, unsigned long duty)
{
Unsigned long tcon;
Unsigned long tcnt;
Unsigned long tcfg1;
Unsigned long t00000;

// For test added byXiaolin. Peng
Unsigned long TCNTB_saver = 0;
Unsigned long TCMPB_saver = 0;

Struct clk * clk_p;
Unsigned long pclk;

// For test added by Xiaolin. Peng
Printk ("freq: % ld \ n", freq );

// Set GPB0 as tout0, pwm output
S3c2410_gpio_cfgpin (S3C2410_GPB (0), S3C2410_GPB0_TOUT0 );

Tcon = _ raw_readl (S3C2410_TCON );
Tcfg1 = _ raw_readl (S3C2410_TCFG1 );
T1_0 = _ raw_readl (s3c2410_t1_0 );

// Prescaler = 50
T00000 & = ~ S3c2410_t1__prescaler0_mask;
T00000 | = (50-1 );

// Mux = 1/16
Tcfg1 & = ~ S3c2410_t1_mux0_mask;
Tcfg1 | = s3c2410_t00000000mux0_div16;

_ Raw_writel (tcfg1, S3C2410_TCFG1 );
_ Raw_writel (t1_0, s3c2410_t1_0 );

Clk_p = clk_get (NULL, "pclk ");
Pclk = clk_get_rate (clk_p );
Tcnt = (pclk/(t1_0 + 1)/16)/freq;

_ Raw_writel (tcnt, S3C2410_TCNTB (0 ));
_ Raw_writel (tcnt * duty)/100, S3C2410_TCMPB (0 ));

// For test add by Xiaolin. Peng
TCNTB_saver = _ raw_readl (S3C2410_TCNTB (0 ));
TCMPB_saver = _ raw_readl (S3C2410_TCMPB (0 ));
Printk ("TCNTB: % ld \ n", TCNTB_saver );
Printk ("TCMPB: % ld \ n", TCMPB_saver );

Tcon & = ~ 0x1f;
Tcon | = 0xb; // disable deadzone, auto-reload, inv-off, update TCNTB0 & TCMPB0, start timer 0
_ Raw_writel (tcon, S3C2410_TCON );

Tcon & = ~ 2; // clear manual update bit
_ Raw_writel (tcon, S3C2410_TCON );
}

Static void PWM_Stop (void)
{
S3c2410_gpio_cfgpin (S3C2410_GPB (0), S3C2410_GPIO_OUTPUT );
S3c2410_gpio_setpin (S3C2410_GPB (0), 0 );
}

Static int s3c24xx_pwm_open (struct inode * inode, struct file * file)
{
If (! Down_trylock (& lock ))
{
Return 0;
}
Else
Return-ebusy;
}

Static int s3c24xx_pwm_close (struct inode * inode, struct file * file)
{
Pwm_stop ();
Up (& lock );
Return 0;
}
// Cmd = 1, open PWM function. = 0, close PWM function
// PWM frquency = (ARG & 0xff00)> 8,
// PWM duty = (arm & 0x00ff)
//
Static int s3c24xx_pwm_ioctl (struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
{
Printk ("ioctl pwm: % d % ld \ n", cmd, arg );
Switch (cmd ){
Case PWM_IOCTL_SET_FREQ:
If (arg = 0)
Return-EINVAL;
PWM_Set_Freq_Duty (arg> 8), (arg & 0xff ));
Break;

Case PWM_IOCTL_STOP:
PWM_Stop ();
Break;
}

Return 0;
}

Static struct file_operations dev_fops = {
. Owner = THIS_MODULE,
. Open = s3c24xx_pwm_open,
. Release = s3c24xx_pwm_close,
. Ioctl = s3c24xx_pwm_ioctl,
};

Static struct miscdevice misc = {
. Minor = MISC_DYNAMIC_MINOR,
. Name = DEVICE_NAME,
. Fops = & dev_fops,
};

Static int _ init dev_init (void)
{
Int ret;

Init_MUTEX (& lock); // init semaphore
Ret = misc_register (& misc );

Printk (device_name "\ tinitialized \ n ");

Return ret;
}

Static void _ exit dev_exit (void)
{
Misc_deregister (& MISC );
}

Module_init (dev_init );
Module_exit (dev_exit );
Module_license ("GPL ");
Module_author ("friendlyarm Inc .");
Module_description ("S3C2410/S3C2440 PWM driver ");

The following code is used to test the driver:

# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <sys/IOCTL. h>

Int main (INT argc, char ** argv)
{
Int on = 1;
Unsigned long frq_duty = 0 ;;
Int FD;

Fprintf (stderr, "pwm app starting... \ n ");

Fd = open ("/dev/pwm", 0 );
If (fd <0 ){
Fprintf (stderr, "error: open device pwm failed \ n ");
Exit (1 );
}
Else {
Fprintf (stderr, "PWM devie open success \ n ");
}
Frq_duty = (200 <8) | 80 );
Ioctl (fd, on, frq_duty );
While (1 );
Close (fd );
Return 0;
}

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.