LP5521/LP5523/LP55231/LP5562/LP8501 通用驱动程序

作者:Milo(Woogyom) Kim <milo.kim@ti.com>

描述

LP5521、LP5523/55231、LP5562 和 LP8501 具有以下通用特性。

通过 I2C 进行寄存器访问 设备初始化/反初始化 为多个输出通道创建 LED 类设备 用于用户空间接口的设备属性 用于运行 LED 模式的程序内存

LP55xx 通用驱动程序使用导出的函数提供这些功能。

lp55xx_init_device() / lp55xx_deinit_device() lp55xx_register_leds() / lp55xx_unregister_leds() lp55xx_regsister_sysfs() / lp55xx_unregister_sysfs()

(驱动程序结构数据)

在 lp55xx 通用驱动程序中,使用了两种不同的数据结构。

  • lp55xx_led

    控制多输出 LED 通道,例如 LED 电流、通道索引。

  • lp55xx_chip

    一般的芯片控制,例如 I2C 和平台数据。

例如,LP5521 最多有 3 个 LED 通道。LP5523/55231 有 9 个输出通道

lp55xx_chip for LP5521 ... lp55xx_led #1
                           lp55xx_led #2
                           lp55xx_led #3

lp55xx_chip for LP5523 ... lp55xx_led #1
                           lp55xx_led #2
                                 .
                                 .
                           lp55xx_led #9

(芯片相关代码)

为了支持特定于设备的配置,使用了特殊的结构 ‘lpxx_device_config’。

  • 最大通道数

  • 复位命令、芯片使能命令

  • 特定于芯片的初始化

  • 亮度控制寄存器访问

  • 设置 LED 输出电流

  • 用于运行模式的程序内存地址访问

  • 其他特定于设备的属性

(固件接口)

LP55xx 系列设备具有用于运行各种 LED 模式的内部程序内存。

此模式数据以文件的形式保存在用户空间中,或者将十六进制字节字符串通过 I2C 写入内存。

LP55xx 通用驱动程序支持固件接口。

LP55xx 芯片有三个程序引擎。

要加载并运行模式,编程顺序如下。

  1. 选择一个引擎编号 (1/2/3)

  2. 模式更改为加载

  3. 将模式数据写入选定区域

  4. 模式更改为运行

LP55xx 通用驱动程序提供如下简单接口。

select_engine

选择哪个引擎用于运行程序

run_engine

启动通过固件接口加载的程序

firmware

加载程序数据

对于 LP5523,还需要一个命令 ‘enginex_leds’。它用于在每个引擎编号处选择 LED 输出。有关更多详细信息,请参阅 ‘lp5523 的内核驱动程序’。

例如,在 LP5521 的引擎 #1 中运行闪烁模式

echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
echo 1 > /sys/class/firmware/lp5521/loading
echo "4000600040FF6000" > /sys/class/firmware/lp5521/data
echo 0 > /sys/class/firmware/lp5521/loading
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine

例如,在 LP55231 的引擎 #3 中运行闪烁模式

两个 LED 被配置为模式输出通道

echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
echo 1 > /sys/class/firmware/lp55231/loading
echo "9d0740ff7e0040007e00a0010000" > /sys/class/firmware/lp55231/data
echo 0 > /sys/class/firmware/lp55231/loading
echo "000001100" > /sys/bus/i2c/devices/xxxx/engine3_leds
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine

同时启动引擎 #2 和 #3 中的闪烁模式

for idx in 2 3
do
echo $idx > /sys/class/leds/red/device/select_engine
sleep 0.1
echo 1 > /sys/class/firmware/lp5521/loading
echo "4000600040FF6000" > /sys/class/firmware/lp5521/data
echo 0 > /sys/class/firmware/lp5521/loading
done
echo 1 > /sys/class/leds/red/device/run_engine

这是 LP5523 的另一个示例。

通过 ‘engine2_leds’ 选择完整的 LED 字符串

echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
echo 1 > /sys/class/firmware/lp5523/loading
echo "9d80400004ff05ff437f0000" > /sys/class/firmware/lp5523/data
echo 0 > /sys/class/firmware/lp5523/loading
echo "111111111" > /sys/bus/i2c/devices/xxxx/engine2_leds
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine

一旦 ‘loading’ 设置为 0,就会调用注册的回调函数。在回调函数内部,加载选定的引擎并更新内存。要运行已编程的模式,应启用 ‘run_engine’ 属性。

LP8501 的模式顺序与 LP5523 类似。

但是模式数据是特定的。

示例 1) 使用引擎 1

echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
echo 1 > /sys/class/firmware/lp8501/loading
echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
echo 0 > /sys/class/firmware/lp8501/loading
echo 1 > /sys/bus/i2c/devices/xxxx/run_engine

示例 2) 同时使用引擎 2 和 3

echo 2 > /sys/bus/i2c/devices/xxxx/select_engine
sleep 1
echo 1 > /sys/class/firmware/lp8501/loading
echo "9d0140ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
echo 0 > /sys/class/firmware/lp8501/loading
sleep 1
echo 3 > /sys/bus/i2c/devices/xxxx/select_engine
sleep 1
echo 1 > /sys/class/firmware/lp8501/loading
echo "9d0340ff7e0040007e00a001c000" > /sys/class/firmware/lp8501/data
echo 0 > /sys/class/firmware/lp8501/loading
sleep 1
echo 1 > /sys/class/leds/d1/device/run_engine

(‘run_engine’ 和 ‘firmware_cb’)

运行程序数据的顺序是通用的。

但是每个设备都有自己的特定命令寄存器地址。

为了支持这一点,‘run_engine’ 和 ‘firmware_cb’ 在每个驱动程序中都是可配置的。

run_engine

控制选定的引擎

firmware_cb

加载固件后执行的回调函数。

用于加载和更新程序内存的芯片特定命令。

(预定义的模式数据)

在没有固件接口的情况下,LP55xx 驱动程序提供了另一种加载 LED 模式的方法。即 ‘预定义’ 模式。

预定义的模式在平台数据中定义,并在需要时通过 sysfs 加载。

要使用预定义模式的概念,应配置 ‘patterns’ 和 ‘num_patterns’。

预定义模式数据的示例

/* mode_1: blinking data */
static const u8 mode_1[] = {
              0x40, 0x00, 0x60, 0x00, 0x40, 0xFF, 0x60, 0x00,
              };

/* mode_2: always on */
static const u8 mode_2[] = { 0x40, 0xFF, };

struct lp55xx_predef_pattern board_led_patterns[] = {
      {
              .r = mode_1,
              .size_r = ARRAY_SIZE(mode_1),
      },
      {
              .b = mode_2,
              .size_b = ARRAY_SIZE(mode_2),
      },
}

struct lp55xx_platform_data lp5562_pdata = {
...
      .patterns      = board_led_patterns,
      .num_patterns  = ARRAY_SIZE(board_led_patterns),
};

然后,可以通过 sysfs 运行 mode_1 和 mode_2

echo 1 > /sys/bus/i2c/devices/xxxx/led_pattern    # red blinking LED pattern
echo 2 > /sys/bus/i2c/devices/xxxx/led_pattern    # blue LED always on

停止运行模式

echo 0 > /sys/bus/i2c/devices/xxxx/led_pattern