This analysis/driver/char/buzzer/x210-buzzer.c the application layer in the buzzer driver code to execute the IOCTL in the corresponding X210_pwm_ioctl function pwm_set_freq, pwm_ Stop two real hardware functions, the X210_PWM_IOTCL function overall code content is as follows
static int x210_pwm_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {switch (cmd) {case PWM_IOCTL_SET_FREQ:PRINTK ("pwm_ioctl_set_freq:\r\n"); if (arg = = 0) return-einval; Pwm_set_freq (ARG); Break;case PWM_IOCTL_STOP:default:printk ("pwm_ioctl_stop:\r\n"); Pwm_stop (); break;} return 0;}
The main analysis of the above code in Pwm_set_freq (ARG) and pwm_stop () two hardware-related functions.
The Pwm_set_freq (ARG) function is responsible for opening the buzzer and setting the frequency of the buzzer to the frequency corresponding to the arg parameter. The Pwm_stop function is responsible for turning off the buzzer.
Pwm_stop function code content is as follows
void Pwm_stop (void) {//Gpd0_2 is set to Inputs3c_gpio_cfgpin (S5pv210_gpd0 (2), S3C_GPIO_SFN (0)); To turn off the buzzer is to set the buzzer pin as the input mode, which is used by the gpiolib to achieve. }
The buzzer is divided into two kinds, one is active buzzer, the other is passive buzzer. A PWM method must be used for the passive buzzer to make the buzzer sound. The active buzzer can be driven by the PWM method, or it can be sent directly to a high level to make the buzzer sound, but the frequency can not be changed.
The code contents of the Pwm_set_freq function are as follows
&NBSP;TCFG0 is set in Uboot,//&NBSP;TIMER0 input frequency is not repeated here finput=pclk/(prescaler1+1)/mux1// =66m/16/ 16// tcfg0 = tcnt = (PCLK/16/16)/freq;// pwm0 output frequency foutput =finput/tcfg0= freqstatic void pwm_set_freq ( unsigned long freq ) {Unsigned long tcon;unsigned long tcnt;unsigned long tcfg1;struct clk *clk_p;unsigned long pclk;//unsigned tmp;//set Gpd0_2 to PWM output S3c_gpio_cfgpin (s5pv210_gpd0 (2), S3C_GPIO_SFN (2) ); Tcon = __raw_readl (S3c2410_tcon); Tcfg1 = __raw_readl (S3C2410_TCFG1);//mux = 1/ 16tcfg1 &= ~ (0xf<<8);tcfg1 |= (0x4<<8); __raw_writel (tcfg1, S3C2410_ TCFG1); Clk_p = clk_get (null, "PCLK"); //clk_get function is a function provided by the kernel, Can be used to read the kernel configuration for some time. Read the PCLK-related structure of the kernel configuration. With Clk_P points to pclk = clk_get_rate (clk_p); //is clk_p from the PCLK structure through the Clk_get_rate function interface, Unit is hztcnt = (PCLK/16/16)/freq; //pclk/16/16 at this point is the frequency of the given timer, in/ The freq gets the frequency of the PWM to be set. __raw_writel (TCNT,&NBSP;S3C2410_TCNTB (2)), __raw_writel (TCNT/2,&NBSP;S3C2410_TCMPB (2));//duty ratio is 50%tcon & = ~ (0xf<<12);tcon |= (0xb<<12);//disable deadzone, auto-reload, Inv-off, update tcntb0&tcmpb0, start timer 0__raw_writel (Tcon, S3C2410_TCON) ; tcon &= ~ (2<<12);//clear manual update bit__raw_writel (tcon, S3C2410_ TCON);}
This article from "Whylinux" blog, declined reprint!
Linux Driver Development Buzzer driver source Analysis (ii)