• 使script.bin文件配置生效的驱动


    1.问题:在全志方案中如果需要设置上拉或者下拉模式,需要在script.bin(先转换为script.fex)中配置gpio口  如:

    但是配置好后是不会生效的,需要写一个驱动来通过读取这个文件的gpio配置来配置相应的寄存器。

    代码:

         #include <linux/init.h>
      2 #include <linux/module.h>
      3 #include <mach/sys_config.h>
      4 #include <mach/pinctrl.h>
      5 #include <asm/io.h>
      6 #include <mach/gpio.h>
      7 
      8 #define PIO_BASE  0x01c20800
      9 typedef volatile unsigned int uint32;
     10 typedef struct {
     11     // gpio口的功能配置寄存器, 每个io口在配置寄存器里占用4位(实际用3位)
     12     uint32 CFGs[4];  //4个功能配置寄存器,每个寄存配置8个io口
     13 
     14     // gpio口的数据寄存器, 每个io口占用一位.
     15     uint32 DAT;
     16 
     17     // gpio口驱动电流配置寄存器, 每个io口占用2位
     18     uint32 DRVs[2]; // 两个寄存器,每个寄存器配置16个io口
     19 
     20     // gpio口上下拉配置寄存器, 每个io口占用2位
     21     uint32 PULLs[2]; // 两个寄存器,每个寄存器配置16个io口
     22 
     23 }PIO_t; //表示每组io口都有的配置寄存器
     24 
     25 
     26 static PIO_t  *pios[7]; // 每个元素分别存放PA, PB, PC, PD, PE, PF, PG组io口的寄存器地址
     27 static u8 *vaddr;
     28 
     29 static int __init h3gpio_init(void)
     30 {
     31     script_item_u *list;
     32     int n, i, j, k;
     33     int sel, pull, drv, level;
     34 
     35     vaddr = ioremap(PIO_BASE, SZ_4K); //映射gpio配置寄存器的基地址
     36     if (NULL == vaddr)
     37         return -ENOMEM;
    
              for (i = 0; i < ARRAY_SIZE(pios); i++) //准备好每组io口的配置寄存器的地址
     40         pios[i] = (PIO_t *)(vaddr+i*0x24);
     41 
     42     // pa的配置寄存器0的地址 ==  &pios[0]->CFG0
     43     n = script_get_pio_list("gpio_para", &list); //返回值为gpio口的个数
     44     if (n <= 0)
     45         return -ENODEV;
     46 
     47     for (i = 0; i < n; i++)
     48     {
     49         //在内核里每组io口都算是32个一组,即使硬件上每组都没有32个io口那么多.
     50         //所以list[i].gpio.gpio / 32 即可算出是第几组,
     51         j = list[i].gpio.gpio >> 5;   // pios[j]就是表示相应组的配置寄存结构体
     52         k = list[i].gpio.gpio & 31;  //算出在组内是第几个io口
     53 
     54         sel = list[i].gpio.mul_sel; //script.bin里io功能选择
     55         pull = list[i].gpio.pull;   //上下拉功能
     56         drv = list[i].gpio.drv_level; //驱动电流等级
     57         level = list[i].gpio.data;  //io口作输出时,输出什么电平
     58 
     59         if (-1 != sel) //功能选择不是<default>
     60         {
     61             pios[j]->CFGs[k>>3] &= ~(0xf << ((k&7)<<2));
     62             pios[j]->CFGs[k>>3] |= sel << ((k&7)<<2);
     63 
     64             if (1 == sel) //如果是输出,还需指定输出的电平
     65             {
     66                 pios[j]->DAT &= ~(1<<k);
     67                 pios[j]->DAT |= level << k;
     68             }
     69         }
     70         if (-1 != pull) //上下拉功能不是<default>
     71         {
     72             pios[j]->PULLs[k>>4] &= ~(3 << ((k&15)<<1));
    
                      pios[j]->PULLs[k>>4] |= pull << ((k&15)<<1);
     74         }
     75 
     76         if (-1 != drv) //驱动电流等级不是<default>
     77         {
     78             pios[j]->DRVs[k>>4] &= ~(3 << ((k&15)<<1));
     79             pios[j]->DRVs[k>>4] |= drv << ((k&15)<<1);
     80         }
     81     }
     82 
     83     return 0;
     84 }
     85 
     86 static void __exit h3gpio_exit(void)
     87 {
     88     iounmap(vaddr);
     89 }
     90 
     91 
     92 module_init(h3gpio_init);
     93 module_exit(h3gpio_exit);
     94 
     95 MODULE_LICENSE("GPL");

    2.Makefile 文件

     1 KDIR := /home/edan/uboot_kernel/orangepi_sdk/source/linux-3.4.112
      2 obj-m += gpio.o
      3 
      4 export ARCH=arm
      5 export CROSS_COMPILE=arm-linux-gnueabihf-
      6 
      7 all:
      8     make -C $(KDIR) modules M=`pwd`
      9 
     10 .PHONY :clean
     11 clean:
     12     
     13     make -C $(KDIR) modules clean M=`pwd`
                                             
  • 相关阅读:
    Some Depth Theory
    Hom和$otimes$如何把我绕晕
    A natrual way to introduce homotopy groups
    指数多项式的Galois群计算
    Trianglated Category and Derived Categories
    最近的代数课上的一些灵魂提问
    致青年朋友的一封信 莫洛亚
    一个函数证明题
    游客的故事
    14. 运算符重载(二)
  • 原文地址:https://www.cnblogs.com/edan/p/9188131.html
Copyright © 2020-2023  润新知