当前位置: 首页 > 嵌入式Linux > 正文

一个x86平台的spi flash驱动移植笔记

最近一个项目,要用到flash存放一些数据,要内核支持。于是又要去移植。

其实,这个项目的合作方式我一直不喜欢,但言语轻微。起初我也不断地提意见,但看了几次的结果后,觉得不提也罢。对于开发人员来说,合作最主要的一点,就是支持力度,至于双赢那些话,我们这层面的人不会关注。这个项目的支持力度一直不给力,要资料也是三番四次的问。

说回这个flash驱动,厂家给的资料只有一个SPI接口的原理图,然后就是flash的手册以及Soc(前面文章多少也提过,这个Soc是Intel的一款芯片)的手册,——就没有然后了。我一开始还对厂家抱有幻想,以为会给demo,谁知后面催的时候却给了人家flash自家写的简单操作demo。关键一点,这个flash同时也存储着BIOS的代码。连我们自己可用的地址范围也是问了好几次才告知。经过自己好几天(其实前后加起来,有2周了)的折腾,加上厂家的支持,最终还是解决了问题,把驱动移植完了。个中滋味,着实难受。

那个flash芯片的操作,其实Linux也支持了。我天真地以为,只要把flash的id填写在那个文件里面就可以了,编译后启动,发现毫无反应。一查才知道,原来没有SPI主机控制器。以前移植某仪器公司的芯片,人家已经实现了主机控制器,所以很容易整合到内核中。现在却不同了。但找遍了内核的配置,没发现有那个Soc类似的控制器代码。于是慌了,问厂家,结果没信息。

于是又在网络上找,经过无序的google搜索,找到一个叫The Chromium Projects的东西,里面有那个SOC的代码。原来这个东西是来自另一个叫coreboot的项目,而coreboot里面有些代码又来自flashroom。无论如何,终于找到一个可以参考的工程了。于是就将里面的spi有关的代码移植到内核中。

为了方便调用,直接用KO的方式在系统运行时加载卸载。在初始化SPI时,发现里面是使用PCI来查询设备的,但coreboot的PCI的代码又不能用于内核,于是又上网了解PCI的知识。对于PCI,一直只闻其名,并没有真正接触过,所以看到直接写一个地址到0xCF8就能拿从0xCFC读取到数据时,从而判断出PCI信息的时候,还是很惊讶的。

解决PCI配置空间的问题后,可以正常找到PCI设备了,接着,加载后内核崩溃,查了好久,才发现是writel的问题,原来内核和coreboot的writel参数是相反的。改正后,可以读取flash的ID的,尝试读取flash的数据,看到有部分不是0xff,初步认为正常——不过,写到flash中的BIOS代码,完全不知道是怎么回事。后来测试写操作,这时又忘记了要先擦除才能写,又耗了一些时间。但写却不成功。擦除倒是正常,有一次测试中,把地址改为0,但忘记注释掉擦除函数,结果把flash的第1个扇区擦除了——这块板子就这样被我搞废了。

我想过可能是写保护的原因,周末利用点时间看看手册,再看看coreboot的代码,发现SPI控制器里面有几个寄存器是可以设置的,于是把代码整理出来,自以为找到了解决方法了。周一来测试,发现情况依旧:还是不能写,写保护还是没法去掉。于是继续查手册,发现几个寄存器的描述中有提到某些位一旦置1后,就不能再写了——而这些位就是锁就是锁住了另外的寄存器。于是猜测是BIOS做了什么事情锁住了寄存器。与此同时,知道了x86中的SMM、SMI这些名词,去网上了解一下资料。得出的结论是:现在这种情况,无法进入SMM,无法改寄存器,无法写flash。然后将测试及疑问发邮件问厂家,我们的最终目的是如何在Linux中使用flash,而不管什么模式什么保护。厂家回复说没在Linux下搞过,只搞过BIOS,然后给出参考步骤,第一步就是禁止写保护功能——而这,正是我们无法做到的一点。

此时,直接进坑了,无法解决。

第二天,厂家给出一个新的BIOS固件,叫我们升级试试。然后我试了,结果成功了!可以正常写了!我直接在flash中写上了惯用的“F”开头的语句。那一刻,很是激动。

最终的解决方法是直接参考coreboot的代码,然后自己封装一个platform设备,调用ioctl来实现读、写、擦除。而不管内核提供的SPI构架。

——一个人奋斗好几天,结果人家一更新bios,就解决了。再次用耗时的教训证明:合作,支持力度十分重要。

后记:

其实这次算是侥幸的了,感谢强大的开源社区!实然也为自己的能力感到羞耻。

想起大学的毕业设计,也是搞了很久,实然找到一个开源的不知是德国人还是法国人写的库(里面的注释还是靠着google翻译才有点看懂),然后就直接拿来用了,然后就解决问题了。

刚来公司时,也是因为一个问题搞了很久,那是一个周末,租房断网,自己拿着公司的本本,去一个同学那里上网继续解决。实然也找到一个类似的模块,又解决了问题。——那天,顶着大太阳走了好远的路。

同时,发现在公司干活或多或少都有坑,或是大坑,或是小坑。

有一次,因为一个接口小板的问题导致一个模块出错,看了半天程序也没找出问题,后来不要接口小板就OK了。又有一次一个IIC驱动问题,查了半天,原来是某仪器他家芯片的BUG,后来也是找技术支持才解决问题。

仅以此文记念那些日子!

李迟,2014年11月21日

本文固定链接: http://www.latelee.org/embedded-linux/x86-spi-flash-porting-note.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: 一个x86平台的spi flash驱动移植笔记 | 迟思堂工作室

一个x86平台的spi flash驱动移植笔记:目前有2 条留言

  1. 1楼
    lx:

    你好,李哥,我想问一下inter E3800 在linux怎么一直移植spi驱动,能在dev里面有设备节点

    2015-06-01 下午6:40 [回复]
    • 你好!这个涉及到linux spi子系统了,spi子系统有其自己的一套构架,开发者需要自己填充各个结构体和函数指针,有点复杂,我就是因为复杂不能快速写出来才用了传统的platform驱动的。

      2015-06-03 下午4:52 [回复]

发表评论

*

快捷键:Ctrl+Enter