在devicetree节点中通过加status来方便的使能或者disable driver

在devicetree的节点下面可以方便的通过status这个变量来使能或者disable driver的probe
例如如果要使能driver的话,可以将status设为okay反之就是disable
dts/mediatek/mt8173-evb.dts:405:    status = "okay";
dts/mediatek/mt8173.dtsi:306:            status = "disabled";
这样在driver的probe函数中可以通过of_device_is_available 来判断probe函数是否要继续下去
    if (!of_device_is_available(mii_np)) {
        ret = -ENODEV;
        goto err_put_node;
    }

static bool __of_device_is_available(const struct device_node *device)
{
    const char *status;
    int statlen;

    if (!device)
        return false;

    status = __of_get_property(device, "status", &statlen);
    if (status == NULL)
        return true;

    if (statlen > 0) {
        if (!strcmp(status, "okay") || !strcmp(status, "ok"))
            return true;
    }

    return false;
}

/**
 *  of_device_is_available - check if a device is available for use
 *
 *  @device: Node to check for availability
 *
 *  Returns true if the status property is absent or set to "okay" or "ok",
 *  false otherwise
 */
bool of_device_is_available(const struct device_node *device)
{
    unsigned long flags;
    bool res;

    raw_spin_lock_irqsave(&devtree_lock, flags);
    res = __of_device_is_available(device);
    raw_spin_unlock_irqrestore(&devtree_lock, flags);
    return res;

}
可见设置ok或者okay 都行,反之只要不是这两个字串,of_device_is_available就返回false,这样probe函数就停止了
因此可以在devicetree节点中通过加status来方便的使能或者disable driver
AM5728是TI公司的一款芯片,其定时器输入捕获PWM的Linux驱动可以通过以下步骤实现: 1. 在设备树中定义定时器和PWM设备节点,包括设备地址、中断号、时钟源等信息。 2. 在内核中编写驱动代码,包括初始化定时器和PWM设备、设置输入捕获模式、中断处理函数等。 3. 在应用层中使用ioctl系统调用配置PWM输出和读取输入捕获值。 具体实现细节可以参考TI公司提供的AM5728参考设计文档和内核源码。 以下是一个简单的驱动程序示例,仅供参考: ```c #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/interrupt.h> #include <linux/pwm.h> #include <linux/timer.h> #include <linux/delay.h> #define TIMER0_BASE 0x48320000 #define PWM0_BASE 0x48302000 #define TIOCP_CFG 0x010 #define TCLR 0x024 #define TCRR 0x028 #define TISR 0x024 #define IRQSTATUS_RAW_0 0x018 /* PWM registers */ #define PWMSS_CTRL 0x40 #define PWMSS_CH0_CTRL 0x100 #define PWMSS_CH0_PERIOD 0x104 #define PWMSS_CH0_DUTY 0x108 static struct timer_list my_timer; static struct pwm_device *pwm_dev; static void *timer0_base, *pwm0_base; static int irq_num; static int pwm_period = 1000000; // 1ms static int pwm_duty = 0; static void my_timer_callback(unsigned long data) { int val; void *base = timer0_base; if(ioread32(base + TISR) & (1 << 4)) // check if capture event occurred { val = ioread32(base + TCRR); // read the timer counter value printk(KERN_INFO "Timer Counter Value: %d\n", val); } mod_timer(&my_timer, jiffies + msecs_to_jiffies(100)); // reschedule the timer } static irqreturn_t my_interrupt_handler(int irq, void *dev_id) { void *base = timer0_base; iowrite32(0x2, base + IRQSTATUS_RAW_0); // clear the interrupt status return IRQ_HANDLED; } static int am5728_pwm_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; void *base; /* Get the base address of the timer0 device */ timer0_base = of_iomap(np, 0); if(!timer0_base) { printk(KERN_ERR "Failed to map timer0 device\n"); return -ENODEV; } /* Get the base address of the PWM0 device */ pwm0_base = ioremap(PWM0_BASE, 0x1000); if(!pwm0_base) { printk(KERN_ERR "Failed to map PWM0 device\n"); return -ENODEV; } /* Configure the timer0 device */ base = timer0_base; iowrite32(0x2, base + TIOCP_CFG); // put the timer in reset mode iowrite32(0, base + TCLR); // disable the timer iowrite32(0xFFFFFFFF, base + TCRR); // set the initial timer count value iowrite32(0x00C2, base + TCLR); // enable the timer in auto-reload mode with prescaler 2 /* Configure the PWM0 device */ pwm_dev = pwm_request(0, "pwm0"); if(IS_ERR(pwm_dev)) { printk(KERN_ERR "Failed to request PWM0 device\n"); return PTR_ERR(pwm_dev); } base = pwm0_base; iowrite32(0x2, base + PWMSS_CTRL); // put the PWM subsystem in reset mode iowrite32(0, base + PWMSS_CH0_CTRL); // disable the PWM channel iowrite32(pwm_period, base + PWMSS_CH0_PERIOD); // set the PWM period iowrite32(pwm_duty, base + PWMSS_CH0_DUTY); // set the PWM duty cycle iowrite32(0x80, base + PWMSS_CH0_CTRL); // enable the PWM channel with active high polarity /* Configure the interrupt */ irq_num = irq_of_parse_and_map(np, 0); if(request_irq(irq_num, my_interrupt_handler, IRQF_TRIGGER_RISING, "am5728_timer0", NULL)) { printk(KERN_ERR "Failed to request interrupt\n"); return -EBUSY; } /* Start the timer */ mod_timer(&my_timer, jiffies + msecs_to_jiffies(100)); printk(KERN_INFO "AM5728 PWM driver initialized\n"); return 0; } static int am5728_pwm_remove(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; /* Stop the timer */ del_timer(&my_timer); /* Free the PWM device */ pwm_free(pwm_dev); /* Release the interrupt */ free_irq(irq_num, NULL); /* Unmap the device memory */ iounmap(pwm0_base); iounmap(timer0_base); printk(KERN_INFO "AM5728 PWM driver removed\n"); return 0; } static struct of_device_id am5728_pwm_of_match[] = { { .compatible = "ti,am5728-pwm", }, {}, }; MODULE_DEVICE_TABLE(of, am5728_pwm_of_match); static struct platform_driver am5728_pwm_driver = { .probe = am5728_pwm_probe, .remove = am5728_pwm_remove, .driver = { .name = "am5728-pwm", .of_match_table = am5728_pwm_of_match, .owner = THIS_MODULE, }, }; static void my_timer_init(void) { init_timer(&my_timer); my_timer.function = my_timer_callback; my_timer.expires = jiffies + msecs_to_jiffies(100); my_timer.data = 0; } static int __init am5728_pwm_init(void) { my_timer_init(); return platform_driver_register(&am5728_pwm_driver); } static void __exit am5728_pwm_exit(void) { platform_driver_unregister(&am5728_pwm_driver); } module_init(am5728_pwm_init); module_exit(am5728_pwm_exit); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("AM5728 PWM driver"); MODULE_LICENSE("GPL"); ``` 注意:以上代码仅供参考,实际情况可能会有所不同,需要根据具体芯片和板子进行修改。同时,使用时需要将代码编译成内核模块并载到内核中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值