Notes d'étude sur le développement de pilotes Linux [4]: Créer automatiquement des nœuds de périphériques + pilote de lumière LED qui obtient des informations de registre via l'arborescence des périphériques

table des matières

Préface

1. Ajouter un nœud d'arborescence de périphériques LED

Acquisition d'informations sur les nœuds d'arborescence de périphériques à deux LED


Préface

Dans le  développement du pilote de lumière LED de la carte de développement Punctual Atom Alpha Linux (crée automatiquement des nœuds de périphérique) , bien que la fonction soit réalisée, elle définit directement l'adresse du registre GPIO de la LED, puis le registre pour l'opération. Cette méthode n'est pas recommandée, et Sous Linux, l'arborescence des périphériques est spécifiquement utilisée pour décrire les informations de périphérique de la carte, il est donc tout à fait possible de définir les informations de registre GPIO de la LED via l'arborescence de périphériques, puis d'utiliser la fonction of dans le pilote de module LED pour obtenir les informations d'attribut du nœud de LED dans l'arborescence de périphériques pour Pour terminer l'écriture du pilote

1. Ajouter un nœud d'arborescence de périphériques LED

Ajoutez les nœuds suivants sous le nœud racine de l'arborescence des périphériques imx6ull-alientek-emmc.dts

/*led节点*/
alphaled{
    #address-cells = <1>;
    #size-cells = <1>;
    compatible = "atkalpha-led";
    status = "okay";
    reg = <0X020C406C 0x04		/*CCM_CCGR1_BASE*/
           0X020E0068 0x04		/*SW_MUX_GPIO1_IO03_BASE*/
           0X020E02F4 0x04		/*SW_PAD_GPIO1_IO03_BASE*/
           0X0209C000 0x04		/*GPIO1_DR_BASE*/
           0X0209C004 0x04>;	/*GPIO1_GDIR_BASE*/
	};

Acquisition d'informations sur les nœuds d'arborescence de périphériques à deux LED

Ajouter à dtsled_fops.dtsled_open pour obtenir des informations de noeud d'arbre de dispositif, d' obtenir des données reg, puis de manipuler directement des registres pour configurer la fonction multiplexage des broches, des propriétés électriques de GPIO, entrée et sortie, et le niveau de défaut

static int dtsled_open(struct inode *inode, struct file *file)
{
    int ret = 0, val;
    struct property *dtsled_prop = NULL;
    const char *str = NULL;
    uint32_t i, regdata[14];

    file->private_data = &dtsled;

    /*1、找到节点 alphaled,路径是 /alphaled */
    dtsled.nd = of_find_node_by_path("/alphaled");
    if (dtsled.nd == NULL){
        printk("alphaled node can not found!\r\n");
        return -EINVAL;
    } else {
        printk("alphaled node has been found!\r\n");
    }

    /*2、查找 兼容性属性*/
    dtsled_prop = of_find_property(dtsled.nd,"compatible",NULL);
    if (dtsled_prop == NULL){
        printk("compatible property find failed\r\n");
        return -EINVAL;
    } else {
        printk("compatible = %s\r\n", (char *)dtsled_prop->value);
    }
    /*3、查找 status 属性*/
    ret = of_property_read_string(dtsled.nd, "status", &str);
    if (ret < 0){
        printk("status read failed!\r\n");
        return -EINVAL;
    } else {
        printk("status = %s\r\n",str);
    }
    /*4、获取reg属性内容*/
    ret = of_property_read_u32_array(dtsled.nd, "reg", regdata, 10);
    if (ret < 0){
        printk("reg property read failed!\r\n");
    } else {
        printk("reg data:\r\n");
        for (i=0; i<10; i++){
            printk("%#X ", regdata[i]);
        }
        printk("\r\n");
    }

    /*初始化led,不能直接操作物理地址,需要地址重映射*/
    /*1、寄存器地址映射*/
#if 0
    IMX6U_CCM_CCGR1   = ioremap(regdata[0], regdata[1]);
    SW_MUX_GPIO1_IO03 = ioremap(regdata[2], regdata[3]);
    SW_PAD_GPIO1_IO03 = ioremap(regdata[4], regdata[5]);
    GPIO1_DR          = ioremap(regdata[6], regdata[7]);
    GPIO1_GDIR        = ioremap(regdata[8], regdata[9]);
#else
    IMX6U_CCM_CCGR1   = of_iomap(dtsled.nd, 0);
    SW_MUX_GPIO1_IO03 = of_iomap(dtsled.nd, 1);
    SW_PAD_GPIO1_IO03 = of_iomap(dtsled.nd, 2);
    GPIO1_DR          = of_iomap(dtsled.nd, 3);
    GPIO1_GDIR        = of_iomap(dtsled.nd, 4);
#endif

    /* 2、使能GPIO1时钟 */
	val = readl(IMX6U_CCM_CCGR1);
	val &= ~(3 << 26);	/* 清楚以前的设置 */
	val |= (3 << 26);	/* 设置新值 */
	writel(val, IMX6U_CCM_CCGR1);

	/* 3、设置GPIO1_IO03的复用功能,将其复用为
	 *    GPIO1_IO03,最后设置IO属性。
	 */
	writel(5, SW_MUX_GPIO1_IO03);
	
	/*寄存器SW_PAD_GPIO1_IO03设置IO属性
	 *bit 16:0 HYS关闭
	 *bit [15:14]: 00 默认下拉
     *bit [13]: 0 kepper功能
     *bit [12]: 1 pull/keeper使能
     *bit [11]: 0 关闭开路输出
     *bit [7:6]: 10 速度100Mhz
     *bit [5:3]: 110 R0/6驱动能力
     *bit [0]: 0 低转换率
	 */
	writel(0x10B0, SW_PAD_GPIO1_IO03);

	/* 4、设置GPIO1_IO03为输出功能 */
	val = readl(GPIO1_GDIR);
	val &= ~(1 << 3);	/* 清除以前的设置 */
	val |= (1 << 3);	/* 设置为输出 */
	writel(val, GPIO1_GDIR);

	/* 5、默认关闭LED */
	val = readl(GPIO1_DR);
	val |= (1 << 3);	
	writel(val, GPIO1_DR);

    return 0;
}

 

 

Je suppose que tu aimes

Origine blog.csdn.net/m0_37845735/article/details/106976227
conseillé
Classement