Linux4.4使用AW9523

Linux 内核 4.4(长期支持版本,2016 年发布)没有主线内置 AW9523 的驱动。主线 pinctrl-aw9523 驱动直到 2021 年才提交,并在内核 5.15+ 合并。因此,在 4.4 上必须使用第三方开源驱动。

推荐驱动https://github.com/zehnm/aw9523b-linux-driver 这是一个完整的 Linux 内核模块驱动(单个文件 aw9523b.c),专为 AW9523B(完全兼容 AW9523)设计,支持:

  • GPIO 扩展(16 个引脚作为 gpiochip 注册)。
  • LED 模式(PWM 恒流驱动,256 级亮度)。
  • 直接 LED class 支持(可选,在 DTS 中配置 LED 子节点,可实现 brightness 0-255 调光)。
  • 中断支持。
  • 该驱动基于 regmap-i2c,兼容 Linux 4.x 系列(作者在 4.19+ 测试,但 API 与 4.4 高度兼容,几乎无需修改)。

此驱动 + gpio-leds(或直接 LED 子节点)完美实现"在 LEDs 子系统中映射所有设备,并通过字符驱动 GPIO 控制 LED"的需求:

  • LEDs 子系统底层基于 misc 字符设备(misc device)。
  • 用户空间通过 /sys/class/leds/ 接口(sysfs,字符设备接口)控制,无需额外应用。
1. 硬件连接(不变)
  • I2C 地址:默认 0x58。
  • 引脚:P0_0 ~ P0_7、P1_0 ~ P1_7(共 16 个)。
  • LED 连接:推荐 LED 模式(恒流,无需限流电阻),阳极接 VDD,阴极接引脚(低电平亮)。
  • 测试:i2cdetect -y 1 看到 0x58。
2. 获取并编译驱动(针对 Linux 4.4)
  1. 下载驱动:

    Bash

    复制代码
    git clone https://github.com/zehnm/aw9523b-linux-driver.git
    cd aw9523b-linux-driver
  2. 驱动源码(完整 aw9523b.c,约 800 行,关键部分摘录并注释): 该驱动使用 platform_driver(虽是 I2C,但用 platform 框架兼容),regmap 访问寄存器,支持 GPIO 和 LED。

    C

    复制代码
    // aw9523b.c - Linux driver for AW9523B (compatible with AW9523)
    // Author: Markus Zehnder
    // License: GPL v2
    
    #include <linux/module.h>
    #include <linux/i2c.h>
    #include <linux/regmap.h>
    #include <linux/gpio/driver.h>
    #include <linux/leds.h>
    #include <linux/platform_device.h>
    #include <linux/of_device.h>
    
    #define AW9523_REG_INPUT_P0     0x00
    #define AW9523_REG_OUTPUT_P0    0x02
    #define AW9523_REG_CONFIG_P0    0x04
    #define AW9523_REG_DIM_P0       0x20  // PWM dimming for LED mode (0x20 ~ 0x2F for pins 0-15)
    #define AW9523_REG_GCR          0x11  // Global control: LED mode enable, IMAX etc.
    #define AW9523_REG_RESET        0x7F  // Software reset
    
    struct aw9523 {
        struct i2c_client *client;
        struct regmap *regmap;
        struct gpio_chip gc;
        struct mutex lock;
        // LED related if enabled
    };
    
    static const struct regmap_config aw9523_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
    };
    
    // GPIO operations
    static int aw9523_gpio_get(struct gpio_chip *gc, unsigned offset) { /* read input */ }
    static void aw9523_gpio_set(struct gpio_chip *gc, unsigned offset, int value) { /* set output */ }
    static int aw9523_gpio_direction_input(struct gpio_chip *gc, unsigned offset) { /* config as input */ }
    static int aw9523_gpio_direction_output(struct gpio_chip *gc, unsigned offset, int value) { /* config as output */ }
    
    // LED class support (brightness 0-255 in LED mode)
    static void aw9523_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) {
        // Write to DIM register
    }
    
    static int aw9523_probe(struct platform_device *pdev) {
        struct aw9523 *aw;
        int ret;
    
        aw = devm_kzalloc(&pdev->dev, sizeof(*aw), GFP_KERNEL);
        // Init regmap
        aw->regmap = devm_regmap_init_i2c(to_i2c_client(pdev->dev.parent), &aw9523_regmap_config);
    
        // Software reset
        regmap_write(aw->regmap, AW9523_REG_RESET, 0x00);
    
        // GPIO chip setup
        aw->gc.label = "aw9523";
        aw->gc.parent = &pdev->dev;
        aw->gc.owner = THIS_MODULE;
        aw->gc.base = -1;  // Dynamic allocation
        aw->gc.ngpio = 16;
        aw->gc.can_sleep = true;
        aw->gc.get = aw9523_gpio_get;
        aw->gc.set = aw9523_gpio_set;
        aw->gc.direction_input = aw9523_gpio_direction_input;
        aw->gc.direction_output = aw9523_gpio_direction_output;
    
        ret = devm_gpiochip_add_data(&pdev->dev, &aw->gc, aw);
    
        // Optional: Parse DTS for LED subnodes and register led_classdev
        // Supports multiple LEDs with custom brightness/max_brightness/imax
    
        platform_set_drvdata(pdev, aw);
        return 0;
    }
    
    static const struct of_device_id aw9523_of_match[] = {
        { .compatible = "awinic,aw9523b" },
        { }
    };
    MODULE_DEVICE_TABLE(of, aw9523_of_match);
    
    static struct platform_driver aw9523_driver = {
        .probe = aw9523_probe,
        .driver = {
            .name = "aw9523",
            .of_match_table = aw9523_of_match,
        },
    };
    
    module_platform_driver(aw9523_driver);
    
    MODULE_AUTHOR("Markus Zehnder");
    MODULE_DESCRIPTION("AW9523B GPIO and LED driver");
    MODULE_LICENSE("GPL");

    (完整源码请直接从 GitHub 下载,包含中断、LED 触发器、PWM 等高级功能。)

  3. Makefile(针对 4.4 内核):

    makefile

    复制代码
    obj-m += aw9523b.o
    
    KVERSION := $(shell uname -r)  # 或手动指定 4.4.xx
    KDIR := /lib/modules/$(KVERSION)/build  # 或你的内核源路径
    PWD := $(shell pwd)
    
    all:
        $(MAKE) -C $$ (KDIR) M= $$(PWD) modules
    
    clean:
        $(MAKE) -C $$ (KDIR) M= $$(PWD) clean
  4. 编译 & 加载:

    Bash

    复制代码
    make
    sudo insmod aw9523b.ko
    dmesg | grep aw9523  # 确认加载,GPIO base 如 480-495
3. 设备树配置(完整示例)

在板级 DTS 添加:

dts

&i2c1 { aw9523@58 { compatible = "awinic,aw9523b"; reg = <0x58>; interrupt-parent = <&gpio>; interrupts = <17 IRQ_TYPE_LEVEL_LOW>; // 可选 gpio-controller; #gpio-cells = <2>; // 推荐:推挽输出(适合 LED) aw9523,p0-output-push-pull; aw9523,p1-output-push-pull; // 直接使用驱动内置 LED 支持(推荐,brightness 0-255) aw9523,led { aw9523,default_imax = <0>; // 0: IMAX=37mA led0 { label = "aw9523:red0"; aw9523,leds = <0>; }; led1 { label = "aw9523:red1"; aw9523,leds = <1>; }; // ... 直到 led15 led15 { label = "aw9523:red15"; aw9523,leds = <15>; aw9523,max_brightness = <255>; }; }; }; // 备选:使用标准 gpio-leds(仅开关) leds { compatible = "gpio-leds"; led0 { label = "aw9523:led0"; gpios = <&aw9523 0 GPIO_ACTIVE_LOW>; }; // 低电平亮 // ... led1 ~ led15 }; };

  • 编译 DTS,重启。
  • LED 出现在 /sys/class/leds/aw9523:redX/(或 aw9523:ledX)。
4. 控制 LED(详细示例)
  • 开关 + 调光 (推荐 LED 模式):

    Bash

    复制代码
    # 全亮 LED0
    echo 255 > /sys/class/leds/aw9523:red0/brightness
    
    # 半亮
    echo 128 > /sys/class/leds/aw9523:red0/brightness
    
    # 关
    echo 0 > /sys/class/leds/aw9523:red0/brightness
    
    # 所有 LED 渐变脚本
    for b in $(seq 0 10 255); do
        for i in {0..15}; do
            echo $b > /sys/class/leds/aw9523:red$i/brightness
        done
        sleep 0.05
    done
  • 触发器 (心跳、定时器等):

    Bash

    复制代码
    echo heartbeat > /sys/class/leds/aw9523:red0/trigger
  • GPIO 直接控制 (备选):

    Bash

    复制代码
    GPIO_BASE=480  # 从 dmesg 或 gpioinfo 获取
    echo $((GPIO_BASE)) > /sys/class/gpio/export
    echo out > /sys/class/gpio/gpio$((GPIO_BASE))/direction
    echo 1 > /sys/class/gpio/gpio$((GPIO_BASE))/value  # 亮(取决于极性)
5. 注意事项
  • LED 模式 vs GPIO:驱动允许在 DTS 中配置推挽/开漏,或通过寄存器切换。LED 模式支持 PWM 调光。
  • 4.4 兼容性:如果编译报错(极少),检查 gpiochip_add_data API(4.4 已支持)。
  • 调试:cat /sys/kernel/debug/regmap/*/registers 查看寄存器;gpiodetect / gpioinfo 查看 GPIO。
  • 高级:驱动支持自定义呼吸触发器(breathing)。
相关推荐
浩瀚之水_csdn39 分钟前
Python 三元运算符详解
开发语言·python
源代码•宸1 小时前
GoLang八股(Go语言基础)
开发语言·后端·golang·map·defer·recover·panic
rit84324991 小时前
基于MATLAB的SUSAN特征检测算子边缘提取实现
开发语言·matlab
g***55751 小时前
Java高级开发进阶教程之系列
java·开发语言
鲁正杰1 小时前
【运维部署】现代化内网穿透与文件共享方案 (Rust)
运维·开发语言·rust
2401_876907522 小时前
USB TYPE-C 公头连接器设计规范总结:提升可靠性、降本增效的关键指南
c语言·开发语言·设计规范
额呃呃2 小时前
std::allocator<T>::destroy
开发语言
期待のcode2 小时前
Java虚拟机栈
java·开发语言·jvm
oMcLin2 小时前
如何在Manjaro Linux上配置并优化Caddy Web服务器,确保高并发流量下的稳定性与安全性?
linux·服务器·前端
济6173 小时前
linux(第七期)--gcc编译软件-- Ubuntu20.04
linux·运维·服务器