向 LinuxSH 添加新板卡¶
Paul Mundt <lethal@linux-sh.org>
本文档试图概述在新的 2.5 和 2.6 内核下,向 LinuxSH 端口添加新板卡的支持所必需的步骤。本文档还试图概述 2.4 和 2.5/2.6 SH 后端之间的一些显著变化。
1. 新的目录结构¶
首先要注意的是新的目录结构。在 2.4 版本下,大多数板卡特定的代码(除了 stboards)都直接放在 arch/sh/kernel/ 中,而板卡特定的头文件则放在 include/asm-sh/ 中。对于新的内核,代码按照板卡类型、配套芯片类型和 CPU 类型进行分类。此目录层次结构的树状视图如下所示:
板卡特定代码
.
|-- arch
| `-- sh
| `-- boards
| |-- adx
| | `-- board-specific files
| |-- bigsur
| | `-- board-specific files
| |
| ... more boards here ...
|
`-- include
`-- asm-sh
|-- adx
| `-- board-specific headers
|-- bigsur
| `-- board-specific headers
|
.. more boards here ...
接下来,对于配套芯片
.
`-- arch
`-- sh
`-- cchips
`-- hd6446x
`-- hd64461
`-- cchip-specific files
等等。配套芯片的头文件与板卡特定的头文件处理方式相同。因此,include/asm-sh/hd64461 是所有 hd64461 特定头文件的所在地。
最后,CPU 系列支持也被抽象出来
.
|-- arch
| `-- sh
| |-- kernel
| | `-- cpu
| | |-- sh2
| | | `-- SH-2 generic files
| | |-- sh3
| | | `-- SH-3 generic files
| | `-- sh4
| | `-- SH-4 generic files
| `-- mm
| `-- This is also broken out per CPU family, so each family can
| have their own set of cache/tlb functions.
|
`-- include
`-- asm-sh
|-- cpu-sh2
| `-- SH-2 specific headers
|-- cpu-sh3
| `-- SH-3 specific headers
`-- cpu-sh4
`-- SH-4 specific headers
应该注意的是,CPU 子类型_没有_被抽象出来。因此,这些仍然需要由 CPU 系列特定的代码处理。
2. 添加新板卡¶
首先要确定的是,您要添加的板卡是独立的,还是属于一个板卡系列,该系列中的大部分板卡可以共享相同的板卡特定代码,只有细微差别。
在第一种情况下,这只是在 arch/sh/boards/ 中为您的板卡创建一个目录,并添加规则以将您的板卡与构建系统连接起来(更多内容将在下一节中介绍)。但是,对于板卡系列,最好有一个通用的顶级 arch/sh/boards/ 目录,然后用每个系列成员的子目录填充它。Solution Engine 和 hp6xx 板卡都是这方面的例子。
在您设置好新的 arch/sh/boards/ 目录后,请记住,您还应该在 include/asm-sh 中为该板卡的本地头文件添加一个目录(如果将有多个)。为了与构建系统无缝互操作,最好让此目录与 arch/sh/boards/ 目录的名称相同,但是如果您的板卡再次属于一个系列,构建系统可以通过某种方式来处理这种情况(通过 incdir-y 重载),您可以随意以系列成员的名称来命名该目录。
每个板卡都需要在 arch/sh/boards 和 include/asm-sh/ 层次结构中拥有一些东西。为了更好地解释这一点,我们使用一些示例来添加一个虚构的板卡。对于设置代码,我们至少需要为 get_system_type() 和 platform_setup() 提供定义。对于我们的虚构板卡,这可能类似于
/*
* arch/sh/boards/vapor/setup.c - Setup code for imaginary board
*/
#include <linux/init.h>
const char *get_system_type(void)
{
return "FooTech Vaporboard";
}
int __init platform_setup(void)
{
/*
* If our hardware actually existed, we would do real
* setup here. Though it's also sane to leave this empty
* if there's no real init work that has to be done for
* this board.
*/
/* Start-up imaginary PCI ... */
/* And whatever else ... */
return 0;
}
我们的新虚构板卡也必须与 machvec 关联,以便它可以发挥任何作用。
machvec 函数分为几个类别
用于 IO 内存(inb 等)和 PCI/主内存(readb 等)的 I/O 函数。
I/O 映射函数(ioport_map、ioport_unmap 等)。
一个“心跳”函数。
PCI 和 IRQ 初始化例程。
一致性分配器(适用于需要特殊分配器的板卡,特别是从一些板卡特定的 SRAM 中分配 DMA 句柄)。
随着时间的推移,machvec 函数会不断添加和删除,因此请始终查阅 include/asm-sh/machvec.h,了解 machvec 的当前状态。
内核会在启动时自动为 machvec 中未定义的函数指针封装通用例程,因为 machvec 函数在整个树中被无条件引用。有些板卡具有极其稀疏的 machvec(例如 dreamcast 和 sh03),而另一些板卡则必须定义几乎所有内容(rts7751r2d)。
添加新机器相对简单(以 vapor 为例)
如果板卡特定的定义非常精简,就像绝大多数板卡的情况一样,那么只需一个板卡特定的头文件就足够了。
添加一个新文件 include/asm-sh/vapor.h,其中包含任何机器特定 IO 函数的原型,这些原型以机器名称为前缀,例如 vapor_inb。在填充机器向量时,将需要这些原型。
请注意,这些原型是通过将 __IO_PREFIX 设置为合理值来自动生成的。一个典型的例子是
#define __IO_PREFIX vapor #include <asm/io_generic.h>在板卡特定的头文件中。任何仍在拥有旧 io.h 的移植板卡都应完全删除它并切换到新模型。
将机器向量定义添加到板卡的 setup.c 中。至少,必须将其定义为如下所示:
struct sh_machine_vector mv_vapor __initmv = { .mv_name = "vapor", }; ALIAS_MV(vapor)最后,添加一个文件 arch/sh/boards/vapor/io.c,其中包含机器特定 io 函数的定义(如果有足够的函数需要)。
3. 与构建系统连接¶
现在我们已经设置了相应的目录,并且所有板卡特定的代码都已就位,是时候看看如何让整个混乱的情况融入构建系统了。
现在,构建系统的很大一部分是完全动态的,只需要在其中各处进行适当的输入即可完成工作。
首先要做的是在 arch/sh/Kconfig 中,在“系统类型”菜单下添加一个条目
config SH_VAPOR
bool "Vapor"
help
select Vapor if configuring for a FooTech Vaporboard.
接下来,必须将其添加到 arch/sh/Makefile 中。所有板卡都需要一个 machdir-y 条目才能进行构建。此条目必须是在 arch/sh/boards 中显示的板卡目录的名称,即使它位于子目录中(在这种情况下,需要列出 arch/sh/boards/ 下面的所有父目录)。对于我们的新板卡,此条目可以如下所示:
machdir-$(CONFIG_SH_VAPOR) += vapor
前提是我们将所有内容都放在 arch/sh/boards/vapor/ 目录中。
接下来,构建系统会假设您的 include/asm-sh 目录的名称也相同。如果情况并非如此(就像属于一个通用系列的多个板卡的情况一样),那么目录名称需要隐式地附加到 incdir-y。现有代码管理 Solution Engine 和 hp6xx 板卡的情况,因此请查看这些代码以获取示例。
一旦解决了这个问题,是时候添加一个 mach 类型的条目了。这是通过在 arch/sh/tools/mach-types 列表的末尾添加一个条目来完成的。执行此操作的方法是不言自明的,因此我们不会在此处浪费空间重复说明。完成此操作后,如果需要,您可以在整个通用代码中的某个位置使用对您的板卡的隐式检查,例如:
/* Make sure we're on the FooTech Vaporboard */
if (!mach_is_vapor())
return -ENODEV;
还要注意,无论 mach-types 条目是否全部大写,mach_is_boardname() 检查都会被隐式强制转换为小写。如果您真的在意,可以阅读该脚本,但是它非常丑陋,因此您可能不想这样做。
现在剩下的就是为您的新板卡提供一个 defconfig。这样,最终使用此板卡的其他人员可以简单地使用此配置作为参考,而不是尝试猜测应该在其中使用哪些设置。
此外,一旦您为您的新板卡复制了示例 .config(假设 arch/sh/configs/vapor_defconfig),您也可以将其直接用作构建目标,并且它将在帮助文本中被隐式列出。
查看“make help”输出,您现在应该看到类似以下内容:
特定于架构的目标 (sh)
zImage
压缩内核映像 (arch/sh/boot/zImage)
adx_defconfig
为 adx 构建
cqreek_defconfig
为 cqreek 构建
dreamcast_defconfig
为 dreamcast 构建
...
vapor_defconfig
为 vapor 构建
然后,这允许您执行以下操作:
$ make ARCH=sh CROSS_COMPILE=sh4-linux- vapor_defconfig vmlinux
这将反过来复制此板卡的 defconfig,通过 oldconfig 运行它(提示您自从创建以来是否有任何新选项),然后开始为您新板卡创建一个功能正常的内核。