|
已编写驱动,在init时已经配置epit为比较输出翻转方式,但加载驱动时没有波形输出。
配置方式及驱动代码如下:
在dtsi中增加配置 epit1: epit@020d0000 { /* EPIT1 */
compatible = "fsl,imx6q-epit1";
reg = <0x020d0000 0x4000>;
interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
};
pinctrl_epit1pwm1: epit1pwmgroup {
fsl,pins = <
MX6QDL_PAD_GPIO_7__EPIT1_OUT 0x1b0b1
>;
};
&epit1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_epit1pwm1>;
status = "okay";
};
clk-imx6q.c中imx6q_clocks_init函数中添加如下代码
clk[IMX6QDL_CLK_EPIT1] = imx_clk_gate2("epit1", "ipg_per", base + 0x6c, 12);
clk_register_clkdev(clk[IMX6QDL_CLK_EPIT1], "per", "imx-epit.1");
编译内核并烧录,再动态加载imx6epit的驱动,驱动代码如下
struct semaphore lock;
static void __iomem *epitbase;
float fFeq = 50.0f; // 频率
int myirq;
#define DEV_NAME "mypwm"
static int mypwm_open(struct inode *inode, struct file *file);
static int mypwm_close(struct inode *inode, struct file *file);
static long mypwm_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static irqreturn_t epit_timer_interrupt(int irq, void *dev_id);
static struct file_operations pwm_fops =
{
.owner = THIS_MODULE,
.open = mypwm_open,
.release = mypwm_close,
.unlocked_ioctl = mypwm_ioctl
};
static struct miscdevice pwm_misc =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "mypwm", //dev/mypwm
.fops = &pwm_fops
};
static int myPWM_Init(void)
{
struct device_node *node;
struct clk *timer_clk;
uint32_t nCycle;
uint32_t epitcr;
int ret;
node = of_find_compatible_node(NULL, NULL,"fsl,imx6q-epit1");
if(node)
{
epitbase = of_iomap(node, 0);
myirq = irq_of_parse_and_map(node, 0);
}
else
{
printk("find compatible err\r\n");
return -1;
}
timer_clk = clk_get_sys("imx-epit.1", "per");
if (IS_ERR(timer_clk))
{
printk("clk get sys err\r\n");
return -1;
}
clk_prepare_enable(timer_clk);
printk("base=%X epit clock=%ld\r\n", (uint32_t)epitbase, clk_get_rate(timer_clk));
__raw_writel(0, epitbase+EPITCR);
__raw_writel(0xffffffff, epitbase + EPITLR);
epitcr = EPITCR_CLKSRC_REF_HIGH | EPITCR_OM_TOGGLE | EPITCR_WAITEN | EPITCR_STOPEN | EPITCR_IOVW
| (EPITCR_CLKDIV(66))| EPITCR_RLD | EPITCR_ENMOD;
__raw_writel(epitcr, epitbase + EPITCR);
// LR
nCycle = 20000-1;
__raw_writel(nCycle, epitbase+EPITLR);
// compare nCycle+10
__raw_writel(10000+1, epitbase+EPITCMPR);
// pin altfunction 引脚复用中配置
// enable epit
__raw_writel(epitcr|EPITCR_EN , epitbase+EPITCR);
ret = request_irq(myirq, &epit_timer_interrupt, 0, DEV_NAME, epitbase);
return ret;
}
static int myPWM_UnInit(void)
{
free_irq(myirq, epitbase);
return 0;
}
static inline void epit_irq_disable(void)
{
u32 val;
val = __raw_readl(epitbase + EPITCR);
val &= ~EPITCR_OCIEN;
__raw_writel(val, epitbase + EPITCR);
}
static inline void epit_irq_enable(void)
{
u32 val;
val = __raw_readl(epitbase + EPITCR);
val |= EPITCR_OCIEN;
__raw_writel(val, epitbase + EPITCR);
}
static void epit_irq_acknowledge(void)
{
__raw_writel(EPITSR_OCIF, epitbase + EPITSR);
}
static void myPWM_Stop(void)
{
uint32_t epitcr;
// disable irq
epitcr = __raw_readl(epitbase + EPITCR);
__raw_writel(epitcr&(~ EPITCR_EN) , epitbase + EPITCR);
}
static void myPWM_SetFreq(uint32_t nFreq)
{
// disable irq
// enable irq
}
static void myPWM_SetDuty(float nDutyPercent)
{
}
static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
{
epit_irq_acknowledge();
// first clear, second set
return IRQ_HANDLED;
}
static int mypwm_open(struct inode *inode, struct file *file)
{
if (!down_trylock(&lock)) //是否获得信号量,是 down_trylock(&lock)=0,否则非 0
return 0;
else
return -EBUSY; //返回错误信息:请求的资源不可用
}
static int mypwm_close(struct inode *inode, struct file *file)
{
myPWM_Stop();
up(&lock); //释放信号量 lock
return 0;
}
static long mypwm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case PWM_DUTY:
break;
case PWM_PERIOD: //if cmd=1 即进入 case PWM_IOCTL_SET_FREQ
if (arg == 0) //如果设置的频率参数是 0
return -EINVAL; //返回错误信息,表示向参数传递了无效的参数
//PWM_Set_Freq(arg); //否则设置频率
break;
case PWM_OFF: // if cmd=2 即进入 case PWM_IOCTL_STOP
myPWM_Stop();
break;
default:
break;
}
return 0;
}
static int pwm_init(void)
{
int ret;
sema_init(&lock, 1);
printk ("\tmypwm initializ...\r\n");
ret = myPWM_Init();
if (ret < 0)
{
return ret;
}
printk ("\tmypwm initialized\r\n");
ret = misc_register(&pwm_misc); //注册一个 misc 设备
return ret;
}
static void pwm_exit(void)
{
myPWM_UnInit();
misc_deregister(&pwm_misc); //注销设备
}
module_init(pwm_init);
module_exit(pwm_exit);
|
|