基于tiny4412的Linux内核移植 -- MMA7660驱动移植(九)

作者信息

作者: 彭东林

邮箱:pengdonglin137@163.com

QQ:405728433

平台简介

开发板:tiny4412ADK + S700 + 4GB Flash

要移植的内核版本:Linux-4.4.0 (支持device tree)

u-boot版本:友善之臂自带的 U-Boot 2010.12 (为支持uImage启动,做了少许改动)

busybox版本:busybox 1.25

交叉编译工具链: arm-none-linux-gnueabi-gcc

      (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29))

摘要

    MMA7660是一个三轴加速度传感器,跟exynos4412之间使用I2C接口进行通信,同时MMA7660可以向exynos4412发起外部中断。

    移植MMA7660驱动会涉及到device tree、I2C驱动、中断、输入子系统等几个部分,tiny4412自带的MMA7660驱动程序是不支持设备树的,同时I2C驱动也没有采用设备树,所以主要的工作量就是将MMA7660和I2C驱动程序从非设备树形式转变为设备树的形式。同时借此机会,学习一下有设备树的情况下的设备驱动(MMA7660和I2C)和中断。

移植

一、原理图

下面是MMA7660的在底板原理图:

image

     可以看到,使用的是第3个I2C控制器。

下面是核心板:

  I2C:

image

   XEINT25:

image

二、tiny4412自带的驱动

    tiny4412自带的mma7660驱动并不是采用设备树,但是可以作为我们的参考,在arch/arm/mach-exynos/mach-tiny4412.c中包含了mma7660的板级信息。

MMA7660的板级信息:

   1: #include <linux/mma7660.h>
   2: static struct mma7660_platform_data mma7660_pdata = {
   3:     .irq            = IRQ_EINT(25),
   4:     .poll_interval    = 100,
   5:     .input_fuzz        = 4,
   6:     .input_flat        = 4,
   7: };
   8:  
   9: static struct s3c2410_platform_i2c tiny4412_i2c3_data __initdata = {
  10:     .flags            = 0,
  11:     .bus_num        = 3,
  12:     .slave_addr        = 0x10,
  13:     .frequency        = 200*1000,
  14:     .sda_delay        = 100,
  15: };
  16:  
  17: static struct i2c_board_info i2c_devs3[] __initdata = {
  18:     {
  19:         I2C_BOARD_INFO("mma7660", 0x4c),
  20:         .platform_data = &mma7660_pdata,
  21:     },
  22: };
  23:  
  24: static void __init smdk4x12_machine_init(void)
  25: {
  26:     ... ...
  27:     s3c_i2c3_set_platdata(&tiny4412_i2c3_data);
  28:     i2c_register_board_info(3, i2c_devs3, ARRAY_SIZE(i2c_devs3));   // 注册板级信息
  29:     ... ...
  30: }

其中,

从上面的信息我们可以知道:

MMA7660的器件地址是0x4c,I2C3的CLK信号新的频率为200KHz。这两个信息比较重要。MMA7660的驱动程序是linux-3.0.86/drivers/hwmon/mma7660.c。

I2C的板级信息:

在arch/arm/plat-samsung/dev-i2c3.c中:

   1: /* linux/arch/arm/plat-samsung/dev-i2c3.c
   2:  *
   3:  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
   4:  *        http://www.samsung.com/
   5:  *
   6:  * S5P series device definition for i2c device 3
   7:  *
   8:  * This program is free software; you can redistribute it and/or modify
   9:  * it under the terms of the GNU General Public License version 2 as
  10:  * published by the Free Software Foundation.
  11:  */
  12:  
  13: #include <linux/gfp.h>
  14: #include <linux/kernel.h>
  15: #include <linux/string.h>
  16: #include <linux/platform_device.h>
  17:  
  18: #include <mach/irqs.h>
  19: #include <mach/map.h>
  20:  
  21: #include <plat/regs-iic.h>
  22: #include <plat/iic.h>
  23: #include <plat/devs.h>
  24: #include <plat/cpu.h>
  25:  
  26: static struct resource s3c_i2c_resource[] = {
  27:     [0] = {
  28:         .start    = S3C_PA_IIC3,
  29:         .end    = S3C_PA_IIC3 + SZ_4K - 1,
  30:         .flags    = IORESOURCE_MEM,
  31:     },
  32:     [1] = {
  33:         .start    = IRQ_IIC3,
  34:         .end    = IRQ_IIC3,
  35:         .flags    = IORESOURCE_IRQ,
  36:     },
  37: };
  38:  
  39: struct platform_device s3c_device_i2c3 = {
  40:     .name        = "s3c2440-i2c",
  41:     .id        = 3,
  42:     .num_resources    = ARRAY_SIZE(s3c_i2c_resource),
  43:     .resource    = s3c_i2c_resource,
  44: };
  45:  
  46: void __init s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *pd)
  47: {
  48:     struct s3c2410_platform_i2c *npd;
  49:  
  50:     if (!pd) {
  51:         pd = &default_i2c_data;
  52:         pd->bus_num = 3;
  53:     }
  54:  
  55:     npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
  56:                    &s3c_device_i2c3);
  57:  
  58:     if (!npd->cfg_gpio)
  59:         npd->cfg_gpio = s3c_i2c3_cfg_gpio;
  60: }

然后会在arch/arm/mach-exynos/mach-tiny4412.c中注册:

   1: static struct platform_device *smdk4x12_devices[] __initdata = {
   2:     ... ...
   3:     &s3c_device_i2c3,
   4:     ... ...
   5: }
   6:  
   7: static void __init smdk4x12_machine_init(void)
   8: {
   9:     ... ...
  10:     platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
  11:     ... ...
  12: }

I2C控制器对应的驱动是linux-3.0.86/drivers/i2c/busses/i2c-s3c2410.c。

三、移植

1、首先把MMA7660和I2C控制器的板级信息转化为设备树的形式,修改arch/arm/boot/dts/exynos4412-tiny4412.dts,添加MMA7660和I2C的硬件信息,可以参考内核文档:Documentation/devicetree/bindings/i2c/i2c.txt和Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt,中断资源的填写可以参考内核文档Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt。

   1: /* MMA7660FC  */
   2: &i2c_3 {
   3:     samsung,i2c-sda-delay = <100>;
   4:     samsung,i2c-slave-addr = <0x10>;
   5:     samsung,i2c-max-bus-freq = <200000>;
   6:     pinctrl-0 = <&i2c3_bus>;
   7:     pinctrl-names = "default";
   8:     status = "okay";
   9:  
  10:     mma7660@4c {
  11:         compatible = "freescale,mma7660";
  12:         reg = <0x4c>;
  13:         interrupt-parent = <&gpx3>;
  14:         interrupts = <1 2>;
  15:         poll_interval = <100>;
  16:         input_fuzz = <4>;
  17:         input_flat = <4>;
  18:         status = "okay";
  19:     };
  20: };

上面的信息基本上是把原来的板级信息搬过来。

第13行和第14行是设置中断资源,参考Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt:

External GPIO and Wakeup Interrupts:
 
The controller supports two types of external interrupts over gpio. The first
is the external gpio interrupt and second is the external wakeup interrupts.
The difference between the two is that the external wakeup interrupts can be
used as system wakeup events.
 
A. External GPIO Interrupts: For supporting external gpio interrupts, the
   following properties should be specified in the pin-controller device node.
 
   - interrupt-parent: phandle of the interrupt parent to which the external
     GPIO interrupts are forwarded to.
   - interrupts: interrupt specifier for the controller. The format and value of
     the interrupt specifier depends on the interrupt parent for the controller.
 
   In addition, following properties must be present in node of every bank
   of pins supporting GPIO interrupts:
 
   - interrupt-controller: identifies the controller node as interrupt-parent.
   - #interrupt-cells: the value of this property should be 2.
     - First Cell: represents the external gpio interrupt number local to the
       external gpio interrupt space of the controller.
     - Second Cell: flags to identify the type of the interrupt
       - 1 = rising edge triggered
       - 2 = falling edge triggered
       - 3 = rising and falling edge triggered
       - 4 = high level triggered
       - 8 = low level triggered

对于interrupts = <1 2>,其中1表示GPX3_1,2表示的是下降沿触发。

第2行的i2c_3是一个标号,i2c3的其他信息是在arch/arm/boot/dts/exynos4.dtsi中:

   1: i2c_3: i2c@13890000 {
   2:     #address-cells = <1>;
   3:     #size-cells = <0>;
   4:     compatible = "samsung,s3c2440-i2c";
   5:     reg = <0x13890000 0x100>;
   6:     interrupts = <0 61 0>;
   7:     clocks = <&clock CLK_I2C3>;
   8:     clock-names = "i2c";
   9:     pinctrl-names = "default";
  10:     pinctrl-0 = <&i2c3_bus>;
  11:     status = "disabled";
  12: };

第10行是设置GPIO的功能复用,i2c3_bus是在文件arch/arm/boot/dts/exynos4x12-pinctrl.dtsi中:

   1: i2c3_bus: i2c3-bus {
   2:     samsung,pins = "gpa1-2", "gpa1-3";
   3:     samsung,pin-function = <3>;
   4:     samsung,pin-pud = <3>;
   5:     samsung,pin-drv = <0>;
   6: };

那么是在什么时候解析这部分,然后设置功能复用的呢?这个以后再说。

2、填写完板级信息,接下来就要移植驱动程序了,其中I2C控制器的驱动程序Linux内核已经写好了,就是drivers/i2c/busses/i2c-s3c2410.c。MMA7660的驱动程序就需要我们自己移植了。

  • 注册
   1: static const struct i2c_device_id mma7660_ids[] = {
   2:     { "mma7660", 0 },
   3:     { },
   4: };
   5: MODULE_DEVICE_TABLE(i2c, mma7660_ids);
   6:  
   7: #ifdef CONFIG_OF
   8: static const struct of_device_id mma7660_dt_match[] = {
   9:     { .compatible = "freescale,mma7660" },
  10:     { }
  11: };
  12: MODULE_DEVICE_TABLE(of, mma7660_dt_match);
  13: #endif
  14:  
  15: static struct i2c_driver mma7660_driver = {
  16:     .driver = {
  17:         .name    = MMA7660_NAME,
  18:         .pm    = &mma7660_pm_ops,
  19:         .of_match_table = of_match_ptr(mma7660_dt_match),
  20:     },
  21:     .probe        = mma7660_probe,
  22:     .remove        = mma7660_remove,
  23:     .id_table    = mma7660_ids,
  24: };
  25:  
  26: module_i2c_driver(mma7660_driver);
  • 解析设备树
   1: static struct mma7660_platform_data *mma7660_parse_dt(struct device *dev)
   2: {
   3:     struct mma7660_platform_data *pdata;
   4:     struct device_node *np = dev->of_node;
   5:  
   6:     if (!np)
   7:         return NULL;
   8:  
   9:     pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  10:     if (!pdata) {
  11:         dev_err(dev, "failed to allocate platform data\n");
  12:         return NULL;
  13:     }
  14:  
  15:     if (of_property_read_u32(np, "poll_interval", &pdata->poll_interval)) {
  16:         dev_err(dev, "failed to get poll_interval property\n");
  17:         return NULL;
  18:     }
  19:  
  20:     if (of_property_read_u32(np, "input_fuzz", &pdata->input_fuzz)) {
  21:         dev_err(dev, "failed to get input_fuzz property\n");
  22:         return NULL;
  23:     }
  24:  
  25:     if (of_property_read_u32(np, "input_flat", &pdata->input_flat)) {
  26:         dev_err(dev, "failed to get input_flat property\n");
  27:         return NULL;
  28:     }
  29:  
  30:     return pdata;
  31: }

关于这部分我已经把代码上传到github上了,下载方法:

git clone https://github.com/pengdonglin137/linux-4.4_tiny4412.git -b port_to_tiny4412

测试

   1: [root@tiny4412 root]# cd /sys/bus/i2c/devices/3-004c/
   2: [root@tiny4412 3-004c]# ls
   3: all_axis_g   input        of_node      subsystem    x_axis_g
   4: driver       modalias     power        tilt_status  y_axis_g
   5: hwmon        name         registers    uevent       z_axis_g
   6: [root@tiny4412 3-004c]# cat all_axis_g 
   7:   2,   0,  22
   8: [root@tiny4412 3-004c]# cat registers 
   9: REG: 0x00 = 0x03 ...... [ 0000 0011 ]
  10: REG: 0x01 = 0x01 ...... [ 0000 0001 ]
  11: REG: 0x02 = 0x16 ...... [ 0001 0110 ]
  12: REG: 0x03 = 0x01 ...... [ 0000 0001 ]
  13: REG: 0x04 = 0x02 ...... [ 0000 0010 ]
  14: REG: 0x05 = 0xa0 ...... [ 1010 0000 ]
  15: REG: 0x06 = 0xe7 ...... [ 1110 0111 ]
  16: REG: 0x07 = 0x59 ...... [ 0101 1001 ]
  17: REG: 0x08 = 0x49 ...... [ 0100 1001 ]
  18: REG: 0x09 = 0x04 ...... [ 0000 0100 ]
  19: REG: 0x0a = 0x0f ...... [ 0000 1111 ]

用hexdump看看上报的事件:

   1: [root@tiny4412 ]# hexdump /dev/input/event0 
   2: 0000000 0013 0000 9b6a 0001 0003 0002 0015 0000
   3: 0000010 0013 0000 9b6a 0001 0000 0000 0000 0000
   4: 0000020 0013 0000 4015 0009 0003 0000 0002 0000
   5: 0000030 0013 0000 4015 0009 0000 0000 0000 0000
   6: 0000040 0018 0000 c6b5 000a 0003 0000 0004 0000
   7: 0000050 0018 0000 c6b5 000a 0000 0000 0000 0000
   8: 0000060 0019 0000 9ef7 0001 0003 0000 0006 0000
   9: 0000070 0019 0000 9ef7 0001 0000 0000 0000 0000
  10: 0000080 0019 0000 c6b3 000a 0003 0000 0005 0000
  11: 0000090 0019 0000 c6b3 000a 0000 0000 0000 0000
  12: 00000a0 0019 0000 d3f0 000d 0003 0000 0004 0000
  13: 00000b0 0019 0000 d3f0 000d 0000 0000 0000 0000
  14: 00000c0 001a 0000 25c1 0003 0003 0000 0003 0000
  15: 00000d0 001a 0000 25c1 0003 0000 0000 0000 0000
  16: 00000e0 001a 0000 32d0 0006 0003 0000 0002 0000
  17: 00000f0 001a 0000 32d0 0006 0000 0000 0000 0000
  18: 0000100 001a 0000 b980 0007 0003 0000 0001 0000
  19: 0000110 001a 0000 b980 0007 0000 0000 0000 0000

未完待续…

转载于:https://www.cnblogs.com/pengdonglin137/p/5240416.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288912.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言简单说】八:分支结构之if...else if()...else...(3)

既然前面几种情况大家都了解了话&#xff0c;这一节的话我就不举例子了。。。 直接上代码&#xff1a; #include<stdio.h> #include<stdlib.h> int main() {int a1;if(a1){printf("a的值等于1\n");}else if(a2){printf("a的值等于2\n"); …

最通俗易懂的依赖注入与控制反转

这是一个关于 ASP.NET 6 依赖注入的系列文章。在这个系列中&#xff0c;我们将了解到什么是依赖注入、控制反转&#xff0c;它能够做什么&#xff0c;以及我们为什么要使用它。之后&#xff0c;我们会进一步了解 ASP.NET 6 依赖注入的生命周期、服务容器等重要概念。最后&#…

word公式编辑器_论文查重算公式吗 公式怎样避免查重?

论文查重算公式吗 公式怎样避免查重?每一个毕业生想要毕业都要经过论文查重这一关&#xff0c;仅有通过了论文查重&#xff0c;才可以进入答辩。在论文检测的情况下&#xff0c;不少同学论文中一定会应用大批量的计算公式&#xff0c;且计算公式全部都是固定不动的&#xff0c…

adb logcat 查看日志

使用 logcat 命令 查看和跟踪系统日志缓冲区的命令logcat的一般用法是&#xff1a; [adb] logcat [<option>] ... [<filter-spec>] ... 下文介绍过滤器和命令选项&#xff0c;详细内容可参见Listing of logcat Command Options。 可以在开发机中通过远程shell的方式…

小程序 - 学习笔记

一、小程序文档笔记 默认开发目录 开发目录解析 1.  app.js、app.json、app.wxss 这三个文件必须有不能删掉。 一个小程序主体部分由这三个文件组成&#xff0c;而且必须放在项目的根目录 js后缀的是脚本文件&#xff0c;调用小程序框架提供的 API—— API 文档json后缀的文件…

【C语言简单说】九:输入

到了下午了&#xff0c;上着班发现没啥事情做… 又来码博客了 ↖(▔&#xff3e;▔)↗ 这一小节我们来说说输入吧。突然想总结以下if语句的&#xff0c;结果发现&#xff0c;还有一个输入没说&#xff1b;之前是不是说过了输出&#xff1f;就是printf这个&#xff0c;现在还有…

java 优秀源码_想要快速进阶Java架构师?这份超强(长)学习计划单 请签收!...

优秀工程师的成长之路就是一条不断打怪升级之路的“修仙之路”&#xff01;而Java程序员一向比别人更难&#xff0c;如果说大家都在修仙的话&#xff0c;java程序员简直神似“剑修”&#xff0c;入行枯燥精通难&#xff0c;要想变得强大&#xff0c;需要能力也需要运气&#xf…

Web Api如何传递POST请求

这里记录一次Web Api传递post请求的例子&#xff0c;由于使用了默认工程的例子&#xff0c;方法名的参数值标记头为FromBody的形式&#xff0c;如下图所示的调用&#xff1a; 调用方式&#xff1a; 那么如果要两个以上的参数如何去实现&#xff0c;这种方式是不行的&#xff0c…

AOT和单文件发布对程序性能的影响

前言这里先和大家介绍一下.NET一些发布的历史&#xff0c;以前的.NET框架原生并不支持最终编译结果的单文件发布&#xff08;需要依赖第三方工具&#xff09;&#xff0c;我这里新建了一个简单的ASP.NET Core项目&#xff0c;发布以后的目录就会像下图这样&#xff0c;里面包含…

无法识别的属性“targetFramework”。请注意属性名称区分大小写。

asp.net部署出错(targetFramework无法识别) 今天尝试着部署了一个基于Framework4.0的web项目&#xff0c;途中发生了一点小小的意外。报的错误是Web.Config配置文件中的 targetFramework属性无法识别。后来查了一下发现在站点中部署的Web使用的是基于.Net Framework2.0的Applic…

.NET点滴:说说Middleware构造中获取不到Scoped服务的问题

今天小桂问我&#xff1a;“为什么中间件的构造函数里不能使用scope的生命周期类型啊&#xff1f;”&#xff0c;那就用实例来得到答案吧&#xff0c;先看小桂说的情况&#xff0c;是报错的&#xff1a;var builder WebApplication.CreateBuilder(args);builder.Services.AddS…

Java游戏有易筋经_当年武侠游戏中绝世秘籍易筋经!重置游戏几十次,玩家才终于找到?...

原标题&#xff1a;当年武侠游戏中绝世秘籍易筋经&#xff01;重置游戏几十次&#xff0c;玩家才终于找到&#xff1f;在金庸的笔下产生过诸多绝世武学&#xff0c;其中最常被人提及的莫过于少林绝学易筋经。这部由达摩祖师于嵩山少林寺面壁9年留下的武学经书&#xff0c;亦是武…

微软是如何解决 PC 端程序多开问题的——内部实现

前言上次&#xff0c;我们通过《引用 Microsoft.VisualBasic 解决程序多开的问题》。虽然它非常简单&#xff0c;但是仅适用于 WinForm 应用程序&#xff0c;而且还需要引用不常用的Microsoft.VisualBasic类库。因此&#xff0c;我们决定深挖一下&#xff0c;看看具体是如何实现…

svn之回滚到指定版本

1 问题 我们用svn下载了最新的代码&#xff0c;但是我们需要回退到制定的版本 2 操作 我们先svn showlog 找到对应的版本号 如果用的是svn图形界面客户端 我们点击关联svn项目的鼠标右键&#xff0c;然后有个update to reversion 写上相应的版本即可

【C语言简单说】十二:逻辑运算符

**总觉得今天更两节就好了。 (&#xffe3;.&#xffe3;) ** 困。。。(&#xffe3;.&#xffe3;) \ 今天我们来加深if的使用&#xff0c;我们来讲解运算符&&和||&#xff0c;一个叫做 与&& 一个叫做 或&&&#xff1b;我们先来说 && 我们…

正则匹配字符串无匹配不到_实现简单正则表达式匹配

这是facebook的面试题实现包含以下特殊字符的正则表达匹配“.” 匹配任意一个字符“*” 匹配任意多个前面的字符例如给定正则表达“ra.”和字符串“ray”你的函数应该返回true&#xff0c;但是仍用这个正则匹配另一个字符串“raymond”应当返回false给定正则表达“.*at”和字符…

【C语言简单说】十三:逻辑运算符||

&#xff08;﹏&#xff09;~ 更完睡觉。 这一节我们来说说逻辑或||&#xff0c;其实很简单的&#xff0c;既然你们理解了第一个逻辑与&#xff0c;那么逻辑或就没什么难度了。 我们说过逻辑与就像我们的并列关系&#xff0c;例如我们吃了苹果和李子。我们现在的逻辑或呢&a…

HQ-day2 C#语言基础

今天主要学习了C#的一些语言基础。 主要有&#xff1a;输入、输出。 一丶输入Console.readline(); 输入语句 输出console.write(); 输出语句 Console.writeline(); 输出语句自动换行 注释 CtrlK 然后 按C &#xff0c;注释选中部分 CtrlK 然后 按U&#xff0c; 取消注释 二、…

【C语言简单说】十三:变量的生命周期

这次我们就来说说生命周期的问题。其实声明周期的意思就是他这个变量的作用范围&#xff0c;啥是作用范围&#xff1f;唔。。。看我举例子吧&#xff0c;意会&#xff0c;意会。。。 首先&#xff0c;我想问一下你们&#xff0c;如果你们校长叫做小明&#xff0c;你们班也有一…

ASP.NET 6 中间件系列 - 条件中间件

这篇文章是 ASP.NET 6 中间件系列文章的第 4 部分。到目前为止&#xff0c;我们已经介绍了 ASP.NET 6 中间件的基础知识&#xff0c;展示了如何创建自定义中间件类&#xff0c;并讨论了中间件执行顺序的重要性。在本系列的最后一部分中&#xff0c;我们将展示在管道中有条件地执…