使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`
                                         

 

posted @ 2018-06-15 17:01  edan  阅读(871)  评论(0编辑  收藏  举报