kernel6.1 新增驱动

MTK Android kernel6.1 新增驱动 Kconfig/Makefile/bzl 通用文档

1. 适用范围

本文档适用于正常 MTK Android 代码结构中的 kernel/kernel6.1 或 vendor kernel module 工程,说明新增一个 kernel driver 时通常需要修改哪些文件。

典型目录可能是:

text 复制代码
kernel/kernel6.1/
kernel/kernel_device_modules-6.1/
device/mediatek/<project>/
vendor/mediatek/

不同项目目录名会有差异,实际以工程中的 BUILD.bazelmodules.bzl*.configvendor_dlkm.modules.load 为准。

如果你的代码是正常 MTK 单工程结构。实际修改时只看当前 lunch/build target 会引用哪些 config fragment、bzl target 和 module load 文件。

2. 总体原则

Android 12 之后的 MTK 项目通常是 GKI/Kleaf 架构。新增项目私有驱动时,推荐做成 vendor module:

text 复制代码
CONFIG_XXX_DRIVER=m

这样会生成 .ko,打包到 vendor_dlkm,对 GKI 影响最小。

不推荐随意改:

text 复制代码
kernel/kernel6.1/arch/arm64/configs/gki_defconfig
kernel/kernel6.1/modules.bzl 中的 GKI/common 模块列表

除非该驱动确实属于 GKI/common kernel 的一部分,并且已经确认不会破坏 ABI/KMI/VTS 要求。

3. 新增驱动需要改哪些东西

新增一个普通驱动通常涉及 5 类文件:

类别 作用 必须性
driver .c 文件 驱动实现 必须
Kconfig 定义 CONFIG_XXX_DRIVER 配置项 必须
MakefileKbuild 根据 CONFIG_XXX_DRIVER 编译目标文件 必须
config fragment / defconfig 打开 CONFIG_XXX_DRIVER=y/m 必须
modules.bzl / BUILD.bazel / module list 声明 .ko 产物进入 Bazel/Kleaf 构建 =m 时必须
vendor_dlkm.modules.load 指定开机自动加载 .ko 需要开机自动加载时必须

4. 推荐路径:做成 vendor module

4.1 放置驱动源码

如果是项目私有驱动,优先放到 vendor kernel module 目录,例如:

text 复制代码
kernel/kernel_device_modules-6.1/drivers/misc/xxx_driver.c

或项目已有的 vendor driver 目录:

text 复制代码
kernel/kernel_device_modules-6.1/drivers/<subsystem>/xxx/

如果你的工程没有单独的 kernel_device_modules-6.1,而是把 vendor driver 也放在 kernel/kernel6.1 里,则可以放到:

text 复制代码
kernel/kernel6.1/drivers/misc/xxx_driver.c

但仍建议以 CONFIG_XXX_DRIVER=m 的方式编成 vendor module。

4.2 修改 Kconfig

示例:驱动放在 drivers/misc/xxx_driver.c

修改:

text 复制代码
kernel/kernel6.1/drivers/misc/Kconfig

或:

text 复制代码
kernel/kernel_device_modules-6.1/drivers/misc/Kconfig

追加:

kconfig 复制代码
config XXX_DRIVER
    tristate "XXX driver"
    depends on OF
    help
      Enable XXX driver for this MTK platform.

如果驱动有单独目录:

text 复制代码
drivers/misc/xxx/Kconfig
drivers/misc/xxx/Makefile
drivers/misc/xxx/xxx_driver.c

则上层 drivers/misc/Kconfig 加:

kconfig 复制代码
source "drivers/misc/xxx/Kconfig"

4.3 修改 Makefile/Kbuild

单文件驱动:

makefile 复制代码
obj-$(CONFIG_XXX_DRIVER) += xxx_driver.o

目录形式驱动:

makefile 复制代码
obj-$(CONFIG_XXX_DRIVER) += xxx/

子目录 drivers/misc/xxx/Makefile

makefile 复制代码
obj-$(CONFIG_XXX_DRIVER) += xxx_driver.o

如果一个驱动由多个 .c 文件组成:

makefile 复制代码
obj-$(CONFIG_XXX_DRIVER) += xxx_driver.o
xxx_driver-y += xxx_core.o
xxx_driver-y += xxx_hw.o
xxx_driver-y += xxx_sysfs.o

CONFIG_XXX_DRIVER=m 时,最终模块名是:

text 复制代码
xxx_driver.ko

5. 修改内核配置

5.1 不要改生成出来的 .config

不要直接改:

text 复制代码
out/.../.config

.config 是编译时生成文件,重新编译后会被覆盖。

应该改源码中的 defconfig 或 config fragment。

5.2 优先找 vendor/project config

在工程根目录搜索:

sh 复制代码
find kernel device vendor \( -name "*defconfig" -o -name "*.config" \)
rg -n "CONFIG_.*=" kernel device vendor -g "*defconfig" -g "*.config"

常见位置包括:

text 复制代码
kernel/kernel_device_modules-6.1/arch/arm64/configs/*.config
kernel/kernel_device_modules-6.1/arch/arm64/configs/*defconfig
kernel/kernel6.1/arch/arm64/configs/*.config
device/mediatek/<project>/*.config
device/mediatek/<project>/*defconfig

项目私有驱动推荐加到 vendor/project config:

text 复制代码
CONFIG_XXX_DRIVER=m

不建议加到:

text 复制代码
kernel/kernel6.1/arch/arm64/configs/gki_defconfig

5.3 如何定位当前产品真正用到的 config

正常 MTK 工程里,不同产品会复用很多 config fragment。最稳的方法是从 build 配置反查当前 target。

先搜当前产品名或 platform 名:

sh 复制代码
rg -n "<project>|<platform>|gki_defconfig|defconfig_fragments|DEFCONFIG|KERNEL_CONFIG" device vendor kernel

再看 bzl/build config 中类似字段:

text 复制代码
build_config
defconfig
defconfig_fragments
pre_defconfig_fragments
post_defconfig_fragments
kernel_config

最终原则:

  1. 当前 build target 引用的 fragment,修改才会生效。
  2. 没被当前 target 引用的 *.config,改了也不会进入最终 .config
  3. 同一个 CONFIG_XXX_DRIVER 如果在多个 fragment 出现,后合入的 fragment 可能覆盖前面的值。

5.4 =m=y 怎么选

配置 结果 是否生成 .ko 是否需要改 bzl/module list 典型用途
CONFIG_XXX_DRIVER=m 编译成模块 项目私有驱动,推荐
CONFIG_XXX_DRIVER=y 编进 kernel image 通常不需要 很早期必须可用的核心驱动
不配置 不编译 功能关闭

推荐:

text 复制代码
CONFIG_XXX_DRIVER=m

只有满足以下情况才考虑 =y

  1. 驱动必须在 very early boot 阶段可用。
  2. 根文件系统、启动链路或关键电源链路依赖它。
  3. 已确认不会破坏 GKI/KMI/VTS 要求。

6. 修改 bzl / BUILD.bazel

6.1 为什么 =m 还要改 bzl

Kconfig/Makefile 只决定 .ko 能不能被编出来。

Bazel/Kleaf 工程还需要知道这个 .ko 是目标产物,否则可能出现:

text 复制代码
CONFIG 已打开,但 out/dist 或 vendor_dlkm 里没有 xxx_driver.ko

所以 CONFIG_XXX_DRIVER=m 时,需要把 .ko 加进对应的 module list。

6.2 先找到项目实际使用的 bzl

搜索:

sh 复制代码
rg -n "module_outs|module_implicit_outs|modules.bzl|vendor_dlkm|MODULES_LIST" kernel device vendor

常见文件:

text 复制代码
kernel/kernel6.1/modules.bzl
kernel/kernel6.1/BUILD.bazel
kernel/kernel_device_modules-6.1/modules.bzl
kernel/kernel_device_modules-6.1/BUILD.bazel
device/mediatek/<project>/*.bzl

6.3 加到 vendor 模块列表

假设生成的模块是:

text 复制代码
drivers/misc/xxx_driver.ko

则在 vendor module list 中加入:

python 复制代码
_VENDOR_MODULES_LIST = [
    # existing modules
    "drivers/misc/xxx_driver.ko",
]

实际变量名可能不是 _VENDOR_MODULES_LIST,也可能叫:

text 复制代码
_MTK_VENDOR_MODULES
_DEVICE_MODULES_LIST
_VENDOR_DLKM_MODULES_LIST
module_outs
module_implicit_outs

原则是:加到 vendor/device module list,不要加到 common GKI module list。

6.4 module_outs 示例

如果工程使用 BUILD.bazel 中的 module_outs

python 复制代码
kernel_build(
    name = "kernel_aarch64",
    outs = [
        "Image",
    ],
    module_outs = [
        # existing modules
        "drivers/misc/xxx_driver.ko",
    ],
)

如果是 vendor kernel module target:

python 复制代码
kernel_module(
    name = "xxx_driver",
    srcs = [
        "drivers/misc/xxx_driver.c",
    ],
    outs = [
        "xxx_driver.ko",
    ],
    kernel_build = "//kernel/kernel6.1:kernel_aarch64",
)

具体写法以你项目已有 target 为准,新增驱动时优先照抄同目录已有驱动的写法。

6.5 不要加错列表

一般不要加到类似下面这种 common/GKI 列表:

python 复制代码
_COMMON_GKI_MODULES_LIST = [
    ...
]

项目私有驱动应该加到 vendor/device list。

7. 修改 modules.load

如果驱动需要开机自动加载,需要加入 vendor module load 文件。

搜索:

sh 复制代码
find device vendor kernel -name "*modules.load*"
rg -n "vendor_dlkm.modules.load|modules.load" device vendor kernel

常见文件:

text 复制代码
device/mediatek/<project>/vendor_dlkm.modules.load
device/mediatek/<project>/vendor_dlkm.modules.load.recovery
vendor/mediatek/proprietary/.../vendor_dlkm.modules.load

追加:

text 复制代码
xxx_driver.ko

注意:

  1. 加到 modules.load 只是自动加载。
  2. 不加也可能可以手动 insmod
  3. 如果驱动需要依赖其他 .ko,依赖模块要先加载,或者依赖 modprobe/modules.dep 处理。

8. Device Tree 配置

如果驱动是 platform driver,通常还需要 DTS 节点。

驱动中:

c 复制代码
static const struct of_device_id xxx_of_match[] = {
    { .compatible = "mediatek,xxx-driver" },
    { }
};
MODULE_DEVICE_TABLE(of, xxx_of_match);

DTS 中:

dts 复制代码
xxx_driver: xxx-driver {
    compatible = "mediatek,xxx-driver";
    status = "okay";
};

如果使用 GPIO/IRQ/clock/regulator,需要在 DTS 中补充:

dts 复制代码
xxx_driver: xxx-driver {
    compatible = "mediatek,xxx-driver";
    xxx-gpios = <&pio 10 GPIO_ACTIVE_HIGH>;
    interrupt-parent = <&pio>;
    interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
    status = "okay";
};

如果 DTS 节点 status = "disabled",即使 .ko 已加载,也不会 probe 该设备。

9. 编译后检查

9.1 检查最终 .config

sh 复制代码
find out -name ".config" -exec grep -H "CONFIG_XXX_DRIVER" {} \;

期望:

text 复制代码
CONFIG_XXX_DRIVER=m

如果没有出现,说明 config fragment 没被当前 target 使用。

9.2 检查 .ko 是否生成

sh 复制代码
find out -name "xxx_driver.ko"

期望能找到:

text 复制代码
out/.../drivers/misc/xxx_driver.ko
out/.../dist/vendor_dlkm/lib/modules/xxx_driver.ko

如果源码目录里生成了,但 dist/vendor_dlkm 里没有,通常是 bzl/module list 没加。

9.3 检查模块是否进入 vendor_dlkm

sh 复制代码
find out -path "*vendor_dlkm*" -name "xxx_driver.ko"

如果找不到,检查:

text 复制代码
modules.bzl / BUILD.bazel
vendor_dlkm.modules.load
BOARD_VENDOR_KERNEL_MODULES
BOARD_VENDOR_RAMDISK_KERNEL_MODULES

具体哪个生效取决于项目构建方式。

10. 板端验证

刷机后检查:

sh 复制代码
adb root
adb shell lsmod | grep xxx
adb shell dmesg | grep -i xxx
adb shell find /vendor_dlkm/lib/modules -name "xxx_driver.ko"

如果没有自动加载:

sh 复制代码
adb shell insmod /vendor_dlkm/lib/modules/xxx_driver.ko
adb shell dmesg | tail

如果 insmod 成功但没有 probe:

  1. 检查 DTS compatible 是否和驱动匹配。
  2. 检查 DTS status 是否为 "okay"
  3. 检查驱动是否注册了 platform_driver / i2c_driver / spi_driver
  4. 检查依赖的 GPIO/IRQ/clock/regulator 是否获取失败。

11. 常见问题

11.1 CONFIG 打开了,但没有 .ko

可能原因:

  1. Makefile 没有加 obj-$(CONFIG_XXX_DRIVER)
  2. Kconfig 没有被上层 source
  3. 改错 config fragment,当前 build target 没用到。
  4. depends on 条件不满足,Kconfig 自动把配置关掉。

11.2 .ko 编出来了,但 vendor_dlkm 里没有

可能原因:

  1. 没有加到 modules.bzl / BUILD.bazel 的 vendor module list。
  2. 加到了 GKI/common list,实际 vendor target 没使用。
  3. 只加了 modules.load,但没有加到 module outputs。

11.3 .ko 在 vendor_dlkm 里,但开机没加载

可能原因:

  1. 没加到 vendor_dlkm.modules.load
  2. 模块依赖没先加载。
  3. 模块签名或版本不匹配。
  4. init 阶段没有加载对应分区的 modules.load。

11.4 模块加载了,但驱动没有 probe

可能原因:

  1. DTS 没有节点。
  2. DTS compatible 字符串不匹配。
  3. DTS status = "disabled"
  4. 设备挂在 I2C/SPI/platform,但 driver 类型写错。
  5. probe 中获取 GPIO/clock/regulator 失败后返回错误。

12. 最小修改清单

drivers/misc/xxx_driver.cCONFIG_XXX_DRIVER=m 为例:

text 复制代码
1. 新增驱动:
   kernel/kernel6.1/drivers/misc/xxx_driver.c
   或 kernel/kernel_device_modules-6.1/drivers/misc/xxx_driver.c

2. 修改 Kconfig:
   drivers/misc/Kconfig

3. 修改 Makefile:
   drivers/misc/Makefile

4. 修改 vendor/project config:
   CONFIG_XXX_DRIVER=m

5. 修改 vendor module bzl/list:
   drivers/misc/xxx_driver.ko

6. 修改 vendor_dlkm.modules.load:
   xxx_driver.ko

7. 如需要自动 probe,修改 DTS:
   compatible = "mediatek,xxx-driver";
   status = "okay";

13. 推荐检查命令

sh 复制代码
# 找 config fragment
find kernel device vendor \( -name "*defconfig" -o -name "*.config" \)

# 找 bzl/module list
rg -n "module_outs|module_implicit_outs|MODULES_LIST|vendor_dlkm" kernel device vendor

# 找 modules.load
find device vendor kernel -name "*modules.load*"

# 编译后检查 CONFIG
find out -name ".config" -exec grep -H "CONFIG_XXX_DRIVER" {} \;

# 编译后检查 ko
find out -name "xxx_driver.ko"

# 板端检查
adb shell lsmod | grep xxx
adb shell dmesg | grep -i xxx

14. 结论

MTK Android kernel6.1 新增项目私有驱动时,推荐路径是:

text 复制代码
驱动源码 + Kconfig + Makefile
        ↓
vendor/project config 中 CONFIG_XXX_DRIVER=m
        ↓
vendor module bzl/module_outs 中加入 xxx_driver.ko
        ↓
vendor_dlkm.modules.load 中加入 xxx_driver.ko
        ↓
DTS 节点 status = "okay"

核心判断:

  1. CONFIG_XXX_DRIVER=m 时,一定要关心 .ko 是否进入 bzl/module list 和 vendor_dlkm
  2. CONFIG_XXX_DRIVER=y 时,通常不用加 .ko list,但会改 kernel image,需谨慎。
  3. 项目私有驱动不要优先改 gki_defconfig 和 GKI/common module list。
相关推荐
行思理2 小时前
fastadmin 新手部分功能点
后端·php
Fanta丶2 小时前
5.Activiti7工作流启动和查询流程、流程任务处理
后端
꒰ঌ 安卓开发໒꒱2 小时前
.NET CAP入门到入土
后端·c#·.net
sukioe3 小时前
【无标题】
后端·docker·centos
geovindu4 小时前
java:Abstract Factory Pattern
java·开发语言·后端·设计模式·抽象工厂模式·创建型模式
geovindu4 小时前
java: Factory Method Pattern
java·开发语言·后端·设计模式·工厂方法模式·创建型模式
voicelen4 小时前
一通电话背后有多少角色?我拆了 Voicelen 的调度台给你看
后端
用户8017220416394 小时前
BarQode:C# 条码二维码生成库
后端
考虑考虑4 小时前
kafka4安装
后端·kafka·自动化运维