向 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 中的“System type”菜单下添加一个条目

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 开发板的此操作,因此请参阅这些示例。

一旦解决了这个问题,就该添加机器类型的条目了。这是通过将条目添加到 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 运行它(提示您自创建以来是否有任何新选项),并开始您为新开发板提供功能内核的过程。