常用linux驱动函数以及例子

 1 常用linux驱动函数

​
//网络


// dma传输
//1申请一个DMA channel
dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
//2根据设备(slave)的特性,配置DMA channel的参数
int dmaengine_slave_config(struct dma_chan *chan, struct dma_slave_config *config)
//3 初始化一个DMA传输描述符
desc=dmaengine_prep_xxx()
//4 将本次传输(transaction)提交给dmaengine并启动传输
dmaengine_submit(desc);//
dma_async_issue_pending(dma_chan);//启动传输
//5 DMA传输完成,都会引发DMA传输描述符的完成回调函数被调用
dmaengine_pcm_dma_complete()

//pinctrl驱动(针对某些功能有多种配置,可以通过下面的函数选择选择配置)
struct pinctrl *devm_pinctrl_get(struct device *dev);
struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name);
int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state);
&usdhc2 {
    pinctrl-names = "default", "state_100mhz", "state_200mhz";
    pinctrl-0 = <&pinctrl_usdhc2_8bit>;
    pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
    pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
    bus-width = <8>;
    non-removable;
    status = "okay";
};
&iomuxc {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_hog_1>;
    imx6ul-evk {
        pinctrl_usdhc2_8bit: usdhc2grp_8bit {
            fsl,pins = <
                MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069
                MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
                MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
                MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
                MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
                MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
                MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
                MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
                MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
                MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
            >;
        };

        pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {
            fsl,pins = <
                MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100b9
                MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170b9
                MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
                MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
                MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
                MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
                MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9
                MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9
                MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9
                MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9
            >;
        };

        pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {
            fsl,pins = <
                MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100f9
                MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170f9
                MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
                MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
                MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
                MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
                MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
                MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
                MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
                MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
            >;
        };
    }
}


//gpio相关操作
gpio = of_get_named_gpio(nd, "gpio_trigger", 0);
gpio_direction_input(gpio);
gpio_direction_output(gpio,0);
gpio_get_value(gpio);
gpio_set_value(gpio,0);

//自旋锁(通过关中断保证原子操作)
spinlock_t lock;
unsigned long flags;
spin_lock_init(&lock);
spin_lock_irqsave(&lock, flags);
spin_unlock_irqrestore(&lock, flags);



// 高精度定时器使用(100000为ns单位)
static enum hrtimer_restart timer_handler(struct hrtimer *timer)
{
    hrtimer_start(&timer, ktime_set(0, 100000), HRTIMER_MODE_REL);
    return HRTIMER_NORESTART;
}
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
timer.function = timer_handler;
hrtimer_start(&timer, ktime_set(0,1000000), HRTIMER_MODE_REL);

//linux内核获取当前时间(us)
do_gettimeofday(&start_time);
//字符串相关函数(其他与c语言一样)
#字符串转数字
char *end;
value = simple_strtol("123456", &end, 10);#10进制

//延时函数
udelay(10)//延时10us
mdelay(10)//延时10ms

//资源申请
devm_kzalloc(dev, sizeof(struct priv_data),

//寄存器操作相关函数
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);

//读写寄存器
long val;
writel(value, base+GPIO1_DR);
val=readl(base+GPIO1_DR);

//申请中断
irq = platform_get_irq(pdev, 0);
irq = irq_of_parse_and_map(np, 0);
ret = devm_request_irq(&pdev->dev, irq, imx2_wdt_isr,0,dev_name(&pdev->dev), pdev);
devm_free_irq(&pdev->dev,irq,pdev);//释放irq

//使能禁止某个中断
void enable_irq(unsigned int irq);//使能某个中断
void disable_irq(unsigned int irq);//禁止某个中断

//使能禁止全局中断
void local_irq_save(unsigned long flags);//保存中断状态
void local_irq_disable(void )//禁止全局中断
//代码
void local_irq_restore(unsigned long flags); //恢复中断状态
void local_irq_enable(void )//使能全局中断

//时钟
wdev->clk = devm_clk_get(&pdev->dev, NULL);
clk_get_rate(wdev->clk);//获取时钟频率
clk_enable(wdev->clk);//使能时钟
clk_disable(wdev->clk);//禁止时钟

//获取of_device_id的data数据
static const struct of_device_id ak4642_of_match[] = {
    { .compatible = "asahi-kasei,ak4642", .data = &ak4642_drvdata},
    { .compatible = "asahi-kasei,ak4643", .data = &ak4643_drvdata},
    {},
};
of_id = of_match_device(ak4642_of_match, &i2c->dev);
drvdata = of_id->data;

//根据指针获得整个结构体
 struct device *dev = container_of(ptr, struct device, kobj);
//@ptr:	the pointer to the member.
//@type:	the type of the container struct this is embedded in.
//@member:	the name of the member within the struct.

//设备树相关(查找设备节点 判断兼容性 映射 获取信息 )

(1)查找设备节点
//根据路径参数,在全局链表of_allnodes中,查找匹配的device_node
of_chosen = of_find_node_by_path("/chosen");
//则根据name在全局链表of_allnodes中查找匹配的device_node
gpiop = of_find_node_by_name(NULL, "gpio");

(2)判断兼容性以及映射
// 判断当前开发板是否兼容设备根节点下的compatible属性
ret = of_machine_is_compatible("fsl,imx6dl");
// 判断设备是否兼容compatible属性
of_device_is_compatible(pdev->dev.of_node, "ti,musb-dm816")
//映射node节点的interrupts属性中的中断
irq_of_parse_and_map(node, 0);
//映射node节点的第1个reg属性
void __iomem *regbase = of_iomap(np, 0);

(3) 从device_node中获取信息
//读取属性名为fsl,wakeup_irq的u32数据
ret=of_property_read_u32(np,"fsl,wakeup_irq",&val);
//读取属性名为reg的u32数组的第0个数值
ret=of_property_read_u32_index(np,"reg",0,&val);
//读取属性名为reg的u32数组
ret=of_property_read_u32_array(np,"reg",table,2);

//读取属性名为status的字符串数据
ret=of_property_read_string(np,"status",&name);
//读取属性名为compatible的字符串数组的第0个字符串
ret=of_property_read_string_index(np, "compatible",0,&name);
//读取属性名为compatible的字符串数组
ret=of_property_read_
int dmaengine_slave_config(struct dma_chan *chan, struct dma_slave_config *config)string_array(np, "compatible",str,2);

​

 2 设备树属性读取例子

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
//设备节点信息
/* 
/{
    aips1: aips-bus@02000000 {
        fec2: ethernet@020b4000 {
            compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
            reg = <0x020b4000 0x4000>;
            interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
                         <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
            clocks = <&clks IMX6UL_CLK_ENET>,
            <&clks IMX6UL_CLK_ENET_AHB>,
            <&clks IMX6UL_CLK_ENET2_REF_125M>;
            clock-names = "ipg", "ahb", "ptp";
            stop-mode = <&gpr 0x10 4>;
            fsl,num-tx-queues=<1>;
            fsl,magic-packet;
            fsl,wakeup_irq = <0>;
            status = "disabled";
        };
    };
}
*/

static int __init chardev_init(void)
{
    int val=0;
    int ret=0;
    int i=0;
    
    int table[5];

    char *name;
    char *str[5];
	struct device_node *np;


    printk("of_fun_test\r\n");
    np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
    if (!np) 
    {
        printk("/soc/ethernet@020b4000 node is not find\n");
        return -1;
    }

    ret=of_device_is_compatible(np,"fsl,imx6ul-fec");
    if(ret==0)
    {
        printk("of_device_is_compatible is not compatible\n"); 
        return -1;
    }
    
    ret=of_property_read_u32(np,"fsl,wakeup_irq",&val);
    printk("of_property_read_u32 fsl,wakeup_irq=%d\n",val); 
    
    ret=of_property_read_u32_index(np,"reg",1,&val);
    printk("of_property_read_u32_index reg=%d\n",val);
    
    ret=of_property_read_u32_array(np,"reg",table,2);
    printk("of_property_read_u32_array reg[0]=%d reg[1]=%d\n",table[0],table[1]);
    
    
    ret=of_property_read_string(np,"status",&name);
    printk("of_property_read_string status=%s\n",name);
    
    ret=of_property_read_string_index(np, "compatible",0,&name);
    printk("of_property_read_string_index compatible=%s\n",name);
    
    ret=of_property_read_string_array(np, "compatible",str,2);
    printk("of_property_read_string_array compatible=%s %s\n",str[0],str[1]); 
    
    
	return 0;
}

static void __exit chardev_exit(void)
{
    printk("chardev device tree exit\r\n");
}

module_init(chardev_init);
module_exit(chardev_exit);

MODULE_AUTHOR("WXQ");
MODULE_LICENSE("GPL");

3 dvem相关函数

//CLOCK
  devm_clk_get()
  devm_clk_put()

//DMA
  dmam_alloc_coherent()
  dmam_alloc_noncoherent()
  dmam_declare_coherent_memory()
  dmam_free_coherent()
  dmam_free_noncoherent()
  dmam_pool_create()
  dmam_pool_destroy()

//GPIO
  devm_gpiod_get()
  devm_gpiod_get_index()
  devm_gpiod_get_index_optional()
  devm_gpiod_get_optional()
  devm_gpiod_put()

//IIO
  devm_iio_device_alloc()
  devm_iio_device_free()
  devm_iio_device_register()
  devm_iio_device_unregister()
  devm_iio_kfifo_allocate()
  devm_iio_kfifo_free()
  devm_iio_trigger_alloc()
  devm_iio_trigger_free()

IO region
  devm_release_mem_region()
  devm_release_region()
  devm_release_resource()
  devm_request_mem_region()
  devm_request_region()
  devm_request_resource()

//IOMAP
  devm_ioport_map()
  devm_ioport_unmap()
  devm_ioremap()
  devm_ioremap_nocache()
  devm_ioremap_wc()
  devm_ioremap_resource() : checks resource, requests memory region, ioremaps
  devm_iounmap()
  pcim_iomap()
  pcim_iomap_regions()	: do request_region() and iomap() on multiple BARs
  pcim_iomap_table()	: array of mapped addresses indexed by BAR
  pcim_iounmap()

//IRQ
  devm_free_irq()
  devm_request_any_context_irq()
  devm_request_irq()
  devm_request_threaded_irq()

//LED
  devm_led_classdev_register()
  devm_led_classdev_unregister()

//MDIO
  devm_mdiobus_alloc()
  devm_mdiobus_alloc_size()
  devm_mdiobus_free()

//MEM
  devm_free_pages()
  devm_get_free_pages()
  devm_kasprintf()
  devm_kcalloc()
  devm_kfree()
  devm_kmalloc()
  devm_kmalloc_array()
  devm_kmemdup()
  devm_kstrdup()
  devm_kvasprintf()
  devm_kzalloc()

//PCI
  pcim_enable_device()	: after success, all PCI ops become managed
  pcim_pin_device()	: keep PCI device enabled after release

//PHY
  devm_usb_get_phy()
  devm_usb_put_phy()

//PINCTRL
  devm_pinctrl_get()
  devm_pinctrl_put()

//PWM
  devm_pwm_get()
  devm_pwm_put()

//REGULATOR
  devm_regulator_bulk_get()
  devm_regulator_get()
  devm_regulator_put()
  devm_regulator_register()

//SLAVE DMA ENGINE
  devm_acpi_dma_controller_register()

//SPI
  devm_spi_register_master()

猜你喜欢

转载自blog.csdn.net/w356877795/article/details/120206669