imx6 WatchDog驱动程序及测试例程

/*
 * Watchdog driver for IMX2 and later processors
 *
 *  Copyright (C) 2010 Wolfram Sang, Pengutronix e.K. <[email protected]>
 *
 * some parts adapted by similar drivers from Darius Augulis and Vladimir
 * Zapolskiy, additional improvements by Wim Van Sebroeck.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * NOTE: MX1 has a slightly different Watchdog than MX2 and later:
 *
 *            MX1:        MX2+:
 *            ----        -----
 * Registers:        32-bit        16-bit
 * Stopable timer:    Yes        No
 * Need to enable clk:    No        Yes
 * Halt on suspend:    Manual        Can be automatic
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/watchdog.h>
#include <linux/clk.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <mach/hardware.h>
#include <mach/irqs.h>

#define DRIVER_NAME "imx2-wdt"

//定义一些宏,方便使用。

#define IMX2_WDT_WCR        0x00        /* Control Register */
#define IMX2_WDT_WCR_WT        (0xFF << 8)    /* -> Watchdog Timeout Field */
#define IMX2_WDT_WCR_WRE    (1 << 3)    /* -> WDOG Reset Enable */
#define IMX2_WDT_WCR_WDE    (1 << 2)    /* -> Watchdog Enable */
#define IMX2_WDT_WCR_WDZST    (1 << 0)    /* -> Watchdog timer Suspend */


#define IMX2_WDT_WSR        0x02        /* Service Register */
#define IMX2_WDT_SEQ1        0x5555        /* -> service sequence 1 */
#define IMX2_WDT_SEQ2        0xAAAA        /* -> service sequence 2 */

#define IMX2_WDT_WICR        0x06        /*Interrupt Control Register*/
#define IMX2_WDT_WICR_WIE    (1 << 15)    /* -> Interrupt Enable */
#define IMX2_WDT_WICR_WTIS    (1 << 14)    /* -> Interrupt Status */
#define IMX2_WDT_WICR_WICT    (0xFF << 0)    /* -> Watchdog Interrupt Timeout Field */

#define IMX2_WDT_MAX_TIME    128
#define IMX2_WDT_DEFAULT_TIME    60        /* in seconds */

#define WDOG_SEC_TO_COUNT(s)    ((s * 2 - 1) << 8)
#define WDOG_SEC_TO_PRECOUNT(s)    (s * 2)        /* set WDOG pre timeout count*/

#define IMX2_WDT_STATUS_OPEN    0
#define IMX2_WDT_STATUS_STARTED    1
#define IMX2_WDT_EXPECT_CLOSE    2

static struct {
    struct clk *clk;
    void __iomem *base;
    unsigned timeout;
    unsigned pretimeout;
    unsigned long status;
    struct timer_list timer;    /* Pings the watchdog when closed */
} imx2_wdt;

static struct miscdevice imx2_wdt_miscdev;

static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);//内核参数
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");


static unsigned timeout = IMX2_WDT_DEFAULT_TIME;
module_param(timeout, uint, 0);//内核参数
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
                __MODULE_STRING(IMX2_WDT_DEFAULT_TIME) ")");

//这个结构体很重要,描述了驱动所支持的操作。
//应用程序使用ioctl GETSUPPORT调用来获取这个结构体
//然后在应用层使用位与检测每一位的功能。
static const struct watchdog_info imx2_wdt_info = {
    .identity = "imx2+ watchdog",
    .options = WDIOF_KEEPALIVEPING | WDIOF_S
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里提供一个简单的 IMX6ULL 键盘驱动程序,适用于 Linux 操作系统: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/input.h> #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/interrupt.h> #define DRIVER_NAME "imx6ull-keyboard" #define MAX_KEYS 4 struct imx6ull_key { const char *name; int gpio; int keycode; int irq; int down; }; static struct imx6ull_key keys[MAX_KEYS] = { { "KEY1", IMX_GPIO_NR(1, 11), KEY_A, -1, 1 }, { "KEY2", IMX_GPIO_NR(1, 12), KEY_B, -1, 1 }, { "KEY3", IMX_GPIO_NR(1, 13), KEY_C, -1, 1 }, { "KEY4", IMX_GPIO_NR(1, 14), KEY_D, -1, 1 }, }; static irqreturn_t imx6ull_key_irq(int irq, void *dev_id) { struct input_dev *input = dev_id; struct imx6ull_key *key = input->private; int down = gpio_get_value(key->gpio); if (down != key->down) { key->down = down; input_report_key(input, key->keycode, down); input_sync(input); } return IRQ_HANDLED; } static int imx6ull_key_probe(struct platform_device *pdev) { struct input_dev *input; int i, ret; input = input_allocate_device(); if (!input) { dev_err(&pdev->dev, "Failed to allocate input device\n"); return -ENOMEM; } input->name = DRIVER_NAME; input->dev.parent = &pdev->dev; input->id.bustype = BUS_GPIO; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; for (i = 0; i < MAX_KEYS; i++) { input->private = &keys[i]; ret = gpio_request(keys[i].gpio, keys[i].name); if (ret) { dev_err(&pdev->dev, "Failed to request GPIO %d\n", keys[i].gpio); goto err_free_input; } gpio_direction_input(keys[i].gpio); keys[i].irq = gpio_to_irq(keys[i].gpio); ret = request_irq(keys[i].irq, imx6ull_key_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, keys[i].name, input); if (ret) { dev_err(&pdev->dev, "Failed to request IRQ %d\n", keys[i].irq); goto err_free_gpio; } } ret = input_register_device(input); if (ret) { dev_err(&pdev->dev, "Failed to register input device\n"); goto err_free_irq; } platform_set_drvdata(pdev, input); return 0; err_free_irq: for (i = 0; i < MAX_KEYS; i++) { if (keys[i].irq >= 0) free_irq(keys[i].irq, input); } err_free_gpio: for (i = 0; i < MAX_KEYS; i++) { if (gpio_is_valid(keys[i].gpio)) gpio_free(keys[i].gpio); } err_free_input: input_free_device(input); return ret; } static int imx6ull_key_remove(struct platform_device *pdev) { struct input_dev *input = platform_get_drvdata(pdev); int i; input_unregister_device(input); for (i = 0; i < MAX_KEYS; i++) { if (keys[i].irq >= 0) free_irq(keys[i].irq, input); if (gpio_is_valid(keys[i].gpio)) gpio_free(keys[i].gpio); } input_free_device(input); return 0; } static const struct of_device_id imx6ull_key_of_match[] = { { .compatible = "fsl,imx6ull-keyboard", }, {}, }; MODULE_DEVICE_TABLE(of, imx6ull_key_of_match); static struct platform_driver imx6ull_key_driver = { .probe = imx6ull_key_probe, .remove = imx6ull_key_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = imx6ull_key_of_match, }, }; module_platform_driver(imx6ull_key_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("IMX6ULL Keyboard Driver"); ``` 这个驱动程序使用了 GPIO 作为输入,并使用了 Linux 内核提供的 input 子系统来产生键盘事件。驱动程序使用了 `input_allocate_device()` 函数来分配输入设备,之后使用 `gpio_request()` 函数来请求 GPIO,并使用 `request_irq()` 函数来请求 IRQ。当 IRQ 发生时,调用 `imx6ull_key_irq()` 函数来处理事件,并使用 `input_report_key()` 函数来报告按键状态。最后,使用 `input_register_device()` 函数来注册输入设备。驱动程序还实现了 `probe()` 和 `remove()` 函数,用于驱动程序的安装和卸载。 请注意,这个驱动程序仅仅是一个简单的例子,并不适用于所有情况。在实际应用中,您需要更加详细的实现和错误处理,以确保驱动程序的稳定性和正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值