drivers: led: Add driver for AXP192/2101 LED control function
Add a driver to support AXP192/2101's LED control function. Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
This commit is contained in:
parent
ff9d35ab95
commit
7237a2659d
@ -4,8 +4,12 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/led.h)
|
||||
|
||||
zephyr_library()
|
||||
|
||||
# zephyr-keep-sorted-start
|
||||
zephyr_library_sources_ifdef(CONFIG_HT16K33 ht16k33.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IS31FL3194 is31fl3194.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IS31FL3216A is31fl3216a.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LED_AXP192_AXP2101 led_axp192.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LED_GPIO led_gpio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LED_NPM1300 led_npm1300.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LED_PWM led_pwm.c)
|
||||
@ -17,8 +21,7 @@ zephyr_library_sources_ifdef(CONFIG_LP5569 lp5569.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NCP5623 ncp5623.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PCA9633 pca9633.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_TLC59108 tlc59108.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IS31FL3194 is31fl3194.c)
|
||||
# zephyr-keep-sorted-stop
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_LED_SHELL led_shell.c)
|
||||
|
||||
|
||||
@ -26,9 +26,13 @@ config LED_SHELL
|
||||
help
|
||||
Enable LED shell for testing.
|
||||
|
||||
# zephyr-keep-sorted-start
|
||||
source "drivers/led/Kconfig.axp192"
|
||||
source "drivers/led/Kconfig.gpio"
|
||||
source "drivers/led/Kconfig.ht16k33"
|
||||
source "drivers/led/Kconfig.is31fl3194"
|
||||
source "drivers/led/Kconfig.is31fl3216a"
|
||||
source "drivers/led/Kconfig.is31fl3733"
|
||||
source "drivers/led/Kconfig.lp3943"
|
||||
source "drivers/led/Kconfig.lp50xx"
|
||||
source "drivers/led/Kconfig.lp5562"
|
||||
@ -39,7 +43,6 @@ source "drivers/led/Kconfig.pca9633"
|
||||
source "drivers/led/Kconfig.pwm"
|
||||
source "drivers/led/Kconfig.tlc59108"
|
||||
source "drivers/led/Kconfig.xec"
|
||||
source "drivers/led/Kconfig.is31fl3733"
|
||||
source "drivers/led/Kconfig.is31fl3194"
|
||||
# zephyr-keep-sorted-stop
|
||||
|
||||
endif # LED
|
||||
|
||||
17
drivers/led/Kconfig.axp192
Normal file
17
drivers/led/Kconfig.axp192
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2024 TOKITA Hiroshi
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config LED_AXP192_AXP2101
|
||||
bool "X-Powers AXP192/AXP2101 LED driver"
|
||||
default y
|
||||
depends on DT_HAS_X_POWERS_AXP192_LED_ENABLED || DT_HAS_X_POWERS_AXP2101_LED_ENABLED
|
||||
depends on DT_HAS_X_POWERS_AXP192_ENABLED || DT_HAS_X_POWERS_AXP2101_ENABLED
|
||||
select I2C
|
||||
select MFD
|
||||
help
|
||||
Enable the AXP192/AXP2101 LED driver.
|
||||
|
||||
AXP192 and AXP2101 are multi-functional integrated Power Management IC (PMIC).
|
||||
This driver is for its LED controller feature.
|
||||
This LED controller can control the lighting using a register,
|
||||
and can also light up in response to the charging status.
|
||||
143
drivers/led/led_axp192.c
Normal file
143
drivers/led/led_axp192.c
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2024 TOKITA Hiroshi
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/led.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(led_axp192, CONFIG_LED_LOG_LEVEL);
|
||||
|
||||
#define CHGLED_OUTPUT_HIZ 0x0
|
||||
#define CHGLED_OUTPUT_SLOW_BLINK 0x1
|
||||
#define CHGLED_OUTPUT_FAST_BLINK 0x2
|
||||
#define CHGLED_OUTPUT_DRIVE_LOW 0x3
|
||||
|
||||
#define CHGLED_OUTPUT_OFFSET 4
|
||||
|
||||
#define CHGLED_ON (CHGLED_OUTPUT_DRIVE_LOW << CHGLED_OUTPUT_OFFSET)
|
||||
#define CHGLED_OFF (CHGLED_OUTPUT_HIZ << CHGLED_OUTPUT_OFFSET)
|
||||
#define CHGLED_BLINK_SLOW (CHGLED_OUTPUT_SLOW_BLINK << CHGLED_OUTPUT_OFFSET)
|
||||
#define CHGLED_BLINK_FAST (CHGLED_OUTPUT_FAST_BLINK << CHGLED_OUTPUT_OFFSET)
|
||||
#define CHGLED_OUTPUT_MASK (BIT_MASK(2) << CHGLED_OUTPUT_OFFSET)
|
||||
|
||||
#define SLOW_BLINK_DELAY_ON (((1000 / 4) / 1) * 1)
|
||||
#define SLOW_BLINK_DELAY_OFF (((1000 / 4) / 1) * 3)
|
||||
#define FAST_BLINK_DELAY_ON (((1000 / 4) / 4) * 1)
|
||||
#define FAST_BLINK_DELAY_OFF (((1000 / 4) / 4) * 3)
|
||||
|
||||
#define CHGLED_CTRL_TYPE_A 0x0
|
||||
#define CHGLED_CTRL_TYPE_B 0x1
|
||||
#define CHGLED_CTRL_BY_REG 0x2
|
||||
#define CHGLED_CTRL_BY_CHARGE 0x3
|
||||
|
||||
#define AXP192_REG_PWROFF_BATTCHK_CHGLED 0x32
|
||||
#define AXP192_REG_CHGLED AXP192_REG_PWROFF_BATTCHK_CHGLED
|
||||
#define AXP192_CHGLED_CTRL_MASK 0x2
|
||||
#define AXP192_CHGLED_CTRL_OFFSET 2
|
||||
|
||||
#define AXP2101_REG_CHGLED 0x69
|
||||
#define AXP2101_CHGLED_CTRL_MASK 0x3
|
||||
#define AXP2101_CHGLED_CTRL_OFFSET 1
|
||||
|
||||
struct led_axp192_config {
|
||||
struct i2c_dt_spec i2c;
|
||||
uint8_t addr;
|
||||
uint8_t mode;
|
||||
uint8_t mode_mask;
|
||||
uint8_t mode_offset;
|
||||
};
|
||||
|
||||
static int led_axp192_on(const struct device *dev, uint32_t led)
|
||||
{
|
||||
const struct led_axp192_config *config = dev->config;
|
||||
|
||||
ARG_UNUSED(led);
|
||||
|
||||
if (config->mode != CHGLED_CTRL_BY_REG) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return i2c_reg_update_byte_dt(&config->i2c, config->addr, CHGLED_OUTPUT_MASK, CHGLED_ON);
|
||||
}
|
||||
|
||||
static int led_axp192_off(const struct device *dev, uint32_t led)
|
||||
{
|
||||
const struct led_axp192_config *config = dev->config;
|
||||
|
||||
ARG_UNUSED(led);
|
||||
|
||||
if (config->mode != CHGLED_CTRL_BY_REG) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return i2c_reg_update_byte_dt(&config->i2c, config->addr, CHGLED_OUTPUT_MASK, CHGLED_OFF);
|
||||
}
|
||||
|
||||
static int led_axp192_blink(const struct device *dev, uint32_t led, uint32_t delay_on,
|
||||
uint32_t delay_off)
|
||||
{
|
||||
const struct led_axp192_config *config = dev->config;
|
||||
|
||||
ARG_UNUSED(led);
|
||||
|
||||
if (config->mode != CHGLED_CTRL_BY_REG) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((delay_on == SLOW_BLINK_DELAY_ON) && (delay_off == SLOW_BLINK_DELAY_OFF)) {
|
||||
return i2c_reg_update_byte_dt(&config->i2c, config->addr, CHGLED_OUTPUT_MASK,
|
||||
CHGLED_BLINK_SLOW);
|
||||
} else if ((delay_on == FAST_BLINK_DELAY_ON) && (delay_off == FAST_BLINK_DELAY_OFF)) {
|
||||
return i2c_reg_update_byte_dt(&config->i2c, config->addr, CHGLED_OUTPUT_MASK,
|
||||
CHGLED_BLINK_FAST);
|
||||
} else {
|
||||
LOG_ERR("The AXP192 blink setting can only %d/%d or %d/%d. (%d/%d)",
|
||||
SLOW_BLINK_DELAY_ON, SLOW_BLINK_DELAY_OFF, FAST_BLINK_DELAY_ON,
|
||||
FAST_BLINK_DELAY_OFF, delay_on, delay_off);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static DEVICE_API(led, led_axp192_api) = {
|
||||
.on = led_axp192_on,
|
||||
.off = led_axp192_off,
|
||||
.blink = led_axp192_blink,
|
||||
};
|
||||
|
||||
static int led_axp192_init(const struct device *dev)
|
||||
{
|
||||
const struct led_axp192_config *config = dev->config;
|
||||
|
||||
switch (config->mode) {
|
||||
case CHGLED_CTRL_TYPE_A:
|
||||
case CHGLED_CTRL_TYPE_B:
|
||||
case CHGLED_CTRL_BY_REG:
|
||||
case CHGLED_CTRL_BY_CHARGE:
|
||||
return i2c_reg_update_byte_dt(&config->i2c, config->addr,
|
||||
config->mode_mask << config->mode_offset,
|
||||
config->mode << config->mode_offset);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#define LED_AXPXXXX_DEFINE(n, model, compat) \
|
||||
static const struct led_axp192_config led_axp_config_##model##_##n = { \
|
||||
.i2c = I2C_DT_SPEC_GET(DT_PARENT(n)), \
|
||||
.addr = AXP##model##_REG_CHGLED, \
|
||||
.mode = UTIL_CAT(CHGLED_CTRL_, DT_STRING_UPPER_TOKEN(n, x_powers_mode)), \
|
||||
.mode_mask = AXP##model##_CHGLED_CTRL_MASK, \
|
||||
.mode_offset = AXP##model##_CHGLED_CTRL_OFFSET, \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_DEFINE(n, led_axp192_init, NULL, NULL, &led_axp_config_##model##_##n, \
|
||||
POST_KERNEL, CONFIG_LED_INIT_PRIORITY, &led_axp192_api);
|
||||
|
||||
#define LED_AXP192_DEFINE(n) LED_AXPXXXX_DEFINE(n, 192, x_powers_axp192_led)
|
||||
#define LED_AXP2101_DEFINE(n) LED_AXPXXXX_DEFINE(n, 2101, x_powers_axp2101_led)
|
||||
|
||||
DT_FOREACH_STATUS_OKAY(x_powers_axp192_led, LED_AXP192_DEFINE)
|
||||
DT_FOREACH_STATUS_OKAY(x_powers_axp2101_led, LED_AXP2101_DEFINE)
|
||||
23
dts/bindings/led/x-powers,axp192-led.yaml
Normal file
23
dts/bindings/led/x-powers,axp192-led.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2024 TOKITA Hiroshi
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
AXP192 LED controller
|
||||
|
||||
The AXP192 has one LED can automatically display error or charging status,
|
||||
or be controlled by software.
|
||||
|
||||
compatible: "x-powers,axp192-led"
|
||||
|
||||
on-bus: axp192
|
||||
|
||||
properties:
|
||||
x-powers,mode:
|
||||
type: string
|
||||
enum:
|
||||
- "by-reg"
|
||||
- "by-charge"
|
||||
description:
|
||||
Select the LED control method.
|
||||
If you select "by-reg", you can control it from software.
|
||||
Please refer to the datasheet for details on "by-charge".
|
||||
24
dts/bindings/led/x-powers,axp2101-led.yaml
Normal file
24
dts/bindings/led/x-powers,axp2101-led.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2024 TOKITA Hiroshi
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
AXP2101 LED controller
|
||||
|
||||
The AXP2101 has one LED can automatically display error or charging status,
|
||||
or be controlled by software.
|
||||
|
||||
compatible: "x-powers,axp2101-led"
|
||||
|
||||
on-bus: axp2101
|
||||
|
||||
properties:
|
||||
x-powers,mode:
|
||||
type: string
|
||||
enum:
|
||||
- "type-a"
|
||||
- "type-b"
|
||||
- "by-reg"
|
||||
description:
|
||||
Select the LED control method.
|
||||
If you select "by-reg", you can control it from software.
|
||||
Please refer to the datasheet for details on "type-a" and "type-b".
|
||||
Loading…
Reference in New Issue
Block a user