mirror of https://github.com/torvalds/linux.git
leds: sy7802: Add support for Silergy SY7802 flash LED controller
The SY7802 is a current-regulated charge pump which can regulate two current levels for Flash and Torch modes. It is a high-current synchronous boost converter with 2-channel high side current sources. Each channel is able to deliver 900mA current. Acked-by: Lee Jones <lee@kernel.org> Signed-off-by: André Apitzsch <git@apitzsch.eu> Link: https://lore.kernel.org/r/20240624-sy7802-v5-2-7abc9d96bfa6@apitzsch.eu Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
parent
a5aff5da79
commit
c581f17a66
|
|
@ -121,4 +121,15 @@ config LEDS_SGM3140
|
|||
This option enables support for the SGM3140 500mA Buck/Boost Charge
|
||||
Pump LED Driver.
|
||||
|
||||
config LEDS_SY7802
|
||||
tristate "LED support for the Silergy SY7802"
|
||||
depends on I2C && OF
|
||||
depends on GPIOLIB
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This option enables support for the SY7802 flash LED controller.
|
||||
SY7802 includes torch and flash functions with programmable current.
|
||||
|
||||
This driver can be built as a module, it will be called "leds-sy7802".
|
||||
|
||||
endif # LEDS_CLASS_FLASH
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ obj-$(CONFIG_LEDS_QCOM_FLASH) += leds-qcom-flash.o
|
|||
obj-$(CONFIG_LEDS_RT4505) += leds-rt4505.o
|
||||
obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o
|
||||
obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o
|
||||
obj-$(CONFIG_LEDS_SY7802) += leds-sy7802.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,539 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Silergy SY7802 flash LED driver with an I2C interface
|
||||
*
|
||||
* Copyright 2024 André Apitzsch <git@apitzsch.eu>
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/led-class-flash.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define SY7802_MAX_LEDS 2
|
||||
#define SY7802_LED_JOINT 2
|
||||
|
||||
#define SY7802_REG_ENABLE 0x10
|
||||
#define SY7802_REG_TORCH_BRIGHTNESS 0xa0
|
||||
#define SY7802_REG_FLASH_BRIGHTNESS 0xb0
|
||||
#define SY7802_REG_FLASH_DURATION 0xc0
|
||||
#define SY7802_REG_FLAGS 0xd0
|
||||
#define SY7802_REG_CONFIG_1 0xe0
|
||||
#define SY7802_REG_CONFIG_2 0xf0
|
||||
#define SY7802_REG_VIN_MONITOR 0x80
|
||||
#define SY7802_REG_LAST_FLASH 0x81
|
||||
#define SY7802_REG_VLED_MONITOR 0x30
|
||||
#define SY7802_REG_ADC_DELAY 0x31
|
||||
#define SY7802_REG_DEV_ID 0xff
|
||||
|
||||
#define SY7802_MODE_OFF 0
|
||||
#define SY7802_MODE_TORCH 2
|
||||
#define SY7802_MODE_FLASH 3
|
||||
#define SY7802_MODE_MASK GENMASK(1, 0)
|
||||
|
||||
#define SY7802_LEDS_SHIFT 3
|
||||
#define SY7802_LEDS_MASK(_id) (BIT(_id) << SY7802_LEDS_SHIFT)
|
||||
#define SY7802_LEDS_MASK_ALL (SY7802_LEDS_MASK(0) | SY7802_LEDS_MASK(1))
|
||||
|
||||
#define SY7802_TORCH_CURRENT_SHIFT 3
|
||||
#define SY7802_TORCH_CURRENT_MASK(_id) \
|
||||
(GENMASK(2, 0) << (SY7802_TORCH_CURRENT_SHIFT * (_id)))
|
||||
#define SY7802_TORCH_CURRENT_MASK_ALL \
|
||||
(SY7802_TORCH_CURRENT_MASK(0) | SY7802_TORCH_CURRENT_MASK(1))
|
||||
|
||||
#define SY7802_FLASH_CURRENT_SHIFT 4
|
||||
#define SY7802_FLASH_CURRENT_MASK(_id) \
|
||||
(GENMASK(3, 0) << (SY7802_FLASH_CURRENT_SHIFT * (_id)))
|
||||
#define SY7802_FLASH_CURRENT_MASK_ALL \
|
||||
(SY7802_FLASH_CURRENT_MASK(0) | SY7802_FLASH_CURRENT_MASK(1))
|
||||
|
||||
#define SY7802_TIMEOUT_DEFAULT_US 512000U
|
||||
#define SY7802_TIMEOUT_MIN_US 32000U
|
||||
#define SY7802_TIMEOUT_MAX_US 1024000U
|
||||
#define SY7802_TIMEOUT_STEPSIZE_US 32000U
|
||||
|
||||
#define SY7802_TORCH_BRIGHTNESS_MAX 8
|
||||
|
||||
#define SY7802_FLASH_BRIGHTNESS_DEFAULT 14
|
||||
#define SY7802_FLASH_BRIGHTNESS_MIN 0
|
||||
#define SY7802_FLASH_BRIGHTNESS_MAX 15
|
||||
#define SY7802_FLASH_BRIGHTNESS_STEP 1
|
||||
|
||||
#define SY7802_FLAG_TIMEOUT BIT(0)
|
||||
#define SY7802_FLAG_THERMAL_SHUTDOWN BIT(1)
|
||||
#define SY7802_FLAG_LED_FAULT BIT(2)
|
||||
#define SY7802_FLAG_TX1_INTERRUPT BIT(3)
|
||||
#define SY7802_FLAG_TX2_INTERRUPT BIT(4)
|
||||
#define SY7802_FLAG_LED_THERMAL_FAULT BIT(5)
|
||||
#define SY7802_FLAG_FLASH_INPUT_VOLTAGE_LOW BIT(6)
|
||||
#define SY7802_FLAG_INPUT_VOLTAGE_LOW BIT(7)
|
||||
|
||||
#define SY7802_CHIP_ID 0x51
|
||||
|
||||
static const struct reg_default sy7802_regmap_defs[] = {
|
||||
{ SY7802_REG_ENABLE, SY7802_LEDS_MASK_ALL },
|
||||
{ SY7802_REG_TORCH_BRIGHTNESS, 0x92 },
|
||||
{ SY7802_REG_FLASH_BRIGHTNESS, SY7802_FLASH_BRIGHTNESS_DEFAULT |
|
||||
SY7802_FLASH_BRIGHTNESS_DEFAULT << SY7802_FLASH_CURRENT_SHIFT },
|
||||
{ SY7802_REG_FLASH_DURATION, 0x6f },
|
||||
{ SY7802_REG_FLAGS, 0x0 },
|
||||
{ SY7802_REG_CONFIG_1, 0x68 },
|
||||
{ SY7802_REG_CONFIG_2, 0xf0 },
|
||||
};
|
||||
|
||||
struct sy7802_led {
|
||||
struct led_classdev_flash flash;
|
||||
struct sy7802 *chip;
|
||||
u8 led_id;
|
||||
};
|
||||
|
||||
struct sy7802 {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct mutex mutex;
|
||||
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct regulator *vin_regulator;
|
||||
|
||||
unsigned int fled_strobe_used;
|
||||
unsigned int fled_torch_used;
|
||||
unsigned int leds_active;
|
||||
int num_leds;
|
||||
struct sy7802_led leds[] __counted_by(num_leds);
|
||||
};
|
||||
|
||||
static int sy7802_torch_brightness_set(struct led_classdev *lcdev, enum led_brightness brightness)
|
||||
{
|
||||
struct sy7802_led *led = container_of(lcdev, struct sy7802_led, flash.led_cdev);
|
||||
struct sy7802 *chip = led->chip;
|
||||
u32 fled_torch_used_tmp;
|
||||
u32 led_enable_mask;
|
||||
u32 enable_mask;
|
||||
u32 torch_mask;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
|
||||
if (chip->fled_strobe_used) {
|
||||
dev_warn(chip->dev, "Cannot set torch brightness whilst strobe is enabled\n");
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (brightness)
|
||||
fled_torch_used_tmp = chip->fled_torch_used | BIT(led->led_id);
|
||||
else
|
||||
fled_torch_used_tmp = chip->fled_torch_used & ~BIT(led->led_id);
|
||||
|
||||
led_enable_mask = led->led_id == SY7802_LED_JOINT ?
|
||||
SY7802_LEDS_MASK_ALL :
|
||||
SY7802_LEDS_MASK(led->led_id);
|
||||
|
||||
val = brightness ? led_enable_mask : SY7802_MODE_OFF;
|
||||
if (fled_torch_used_tmp)
|
||||
val |= SY7802_MODE_TORCH;
|
||||
|
||||
/* Disable torch to apply brightness */
|
||||
ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, SY7802_MODE_MASK,
|
||||
SY7802_MODE_OFF);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
torch_mask = led->led_id == SY7802_LED_JOINT ?
|
||||
SY7802_TORCH_CURRENT_MASK_ALL :
|
||||
SY7802_TORCH_CURRENT_MASK(led->led_id);
|
||||
|
||||
/* Register expects brightness between 0 and MAX_BRIGHTNESS - 1 */
|
||||
if (brightness)
|
||||
brightness -= 1;
|
||||
|
||||
brightness |= (brightness << SY7802_TORCH_CURRENT_SHIFT);
|
||||
|
||||
ret = regmap_update_bits(chip->regmap, SY7802_REG_TORCH_BRIGHTNESS, torch_mask, brightness);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
enable_mask = SY7802_MODE_MASK | led_enable_mask;
|
||||
ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, enable_mask, val);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
chip->fled_torch_used = fled_torch_used_tmp;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&chip->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sy7802_flash_brightness_set(struct led_classdev_flash *fl_cdev, u32 brightness)
|
||||
{
|
||||
struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
|
||||
struct led_flash_setting *s = &fl_cdev->brightness;
|
||||
u32 val = (brightness - s->min) / s->step;
|
||||
struct sy7802 *chip = led->chip;
|
||||
u32 flash_mask;
|
||||
int ret;
|
||||
|
||||
val |= (val << SY7802_FLASH_CURRENT_SHIFT);
|
||||
flash_mask = led->led_id == SY7802_LED_JOINT ?
|
||||
SY7802_FLASH_CURRENT_MASK_ALL :
|
||||
SY7802_FLASH_CURRENT_MASK(led->led_id);
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
ret = regmap_update_bits(chip->regmap, SY7802_REG_FLASH_BRIGHTNESS, flash_mask, val);
|
||||
mutex_unlock(&chip->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sy7802_strobe_set(struct led_classdev_flash *fl_cdev, bool state)
|
||||
{
|
||||
struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
|
||||
struct sy7802 *chip = led->chip;
|
||||
u32 fled_strobe_used_tmp;
|
||||
u32 led_enable_mask;
|
||||
u32 enable_mask;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
|
||||
if (chip->fled_torch_used) {
|
||||
dev_warn(chip->dev, "Cannot set strobe brightness whilst torch is enabled\n");
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (state)
|
||||
fled_strobe_used_tmp = chip->fled_strobe_used | BIT(led->led_id);
|
||||
else
|
||||
fled_strobe_used_tmp = chip->fled_strobe_used & ~BIT(led->led_id);
|
||||
|
||||
led_enable_mask = led->led_id == SY7802_LED_JOINT ?
|
||||
SY7802_LEDS_MASK_ALL :
|
||||
SY7802_LEDS_MASK(led->led_id);
|
||||
|
||||
val = state ? led_enable_mask : SY7802_MODE_OFF;
|
||||
if (fled_strobe_used_tmp)
|
||||
val |= SY7802_MODE_FLASH;
|
||||
|
||||
enable_mask = SY7802_MODE_MASK | led_enable_mask;
|
||||
ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, enable_mask, val);
|
||||
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
chip->fled_strobe_used = fled_strobe_used_tmp;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&chip->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sy7802_strobe_get(struct led_classdev_flash *fl_cdev, bool *state)
|
||||
{
|
||||
struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
|
||||
struct sy7802 *chip = led->chip;
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
*state = !!(chip->fled_strobe_used & BIT(led->led_id));
|
||||
mutex_unlock(&chip->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sy7802_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout)
|
||||
{
|
||||
struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
|
||||
struct led_flash_setting *s = &fl_cdev->timeout;
|
||||
u32 val = (timeout - s->min) / s->step;
|
||||
struct sy7802 *chip = led->chip;
|
||||
|
||||
return regmap_write(chip->regmap, SY7802_REG_FLASH_DURATION, val);
|
||||
}
|
||||
|
||||
static int sy7802_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault)
|
||||
{
|
||||
struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash);
|
||||
struct sy7802 *chip = led->chip;
|
||||
u32 val, led_faults = 0;
|
||||
int ret;
|
||||
|
||||
/* NOTE: reading register clears fault status */
|
||||
ret = regmap_read(chip->regmap, SY7802_REG_FLAGS, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & (SY7802_FLAG_FLASH_INPUT_VOLTAGE_LOW | SY7802_FLAG_INPUT_VOLTAGE_LOW))
|
||||
led_faults |= LED_FAULT_INPUT_VOLTAGE;
|
||||
|
||||
if (val & SY7802_FLAG_THERMAL_SHUTDOWN)
|
||||
led_faults |= LED_FAULT_OVER_TEMPERATURE;
|
||||
|
||||
if (val & SY7802_FLAG_TIMEOUT)
|
||||
led_faults |= LED_FAULT_TIMEOUT;
|
||||
|
||||
*fault = led_faults;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct led_flash_ops sy7802_flash_ops = {
|
||||
.flash_brightness_set = sy7802_flash_brightness_set,
|
||||
.strobe_set = sy7802_strobe_set,
|
||||
.strobe_get = sy7802_strobe_get,
|
||||
.timeout_set = sy7802_timeout_set,
|
||||
.fault_get = sy7802_fault_get,
|
||||
};
|
||||
|
||||
static void sy7802_init_flash_brightness(struct led_classdev_flash *fl_cdev)
|
||||
{
|
||||
struct led_flash_setting *s;
|
||||
|
||||
/* Init flash brightness setting */
|
||||
s = &fl_cdev->brightness;
|
||||
s->min = SY7802_FLASH_BRIGHTNESS_MIN;
|
||||
s->max = SY7802_FLASH_BRIGHTNESS_MAX;
|
||||
s->step = SY7802_FLASH_BRIGHTNESS_STEP;
|
||||
s->val = SY7802_FLASH_BRIGHTNESS_DEFAULT;
|
||||
}
|
||||
|
||||
static void sy7802_init_flash_timeout(struct led_classdev_flash *fl_cdev)
|
||||
{
|
||||
struct led_flash_setting *s;
|
||||
|
||||
/* Init flash timeout setting */
|
||||
s = &fl_cdev->timeout;
|
||||
s->min = SY7802_TIMEOUT_MIN_US;
|
||||
s->max = SY7802_TIMEOUT_MAX_US;
|
||||
s->step = SY7802_TIMEOUT_STEPSIZE_US;
|
||||
s->val = SY7802_TIMEOUT_DEFAULT_US;
|
||||
}
|
||||
|
||||
static int sy7802_led_register(struct device *dev, struct sy7802_led *led,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct led_init_data init_data = {};
|
||||
int ret;
|
||||
|
||||
init_data.fwnode = of_fwnode_handle(np);
|
||||
|
||||
ret = devm_led_classdev_flash_register_ext(dev, &led->flash, &init_data);
|
||||
if (ret) {
|
||||
dev_err(dev, "Couldn't register flash %d\n", led->led_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sy7802_init_flash_properties(struct device *dev, struct sy7802_led *led,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct led_classdev_flash *flash = &led->flash;
|
||||
struct led_classdev *lcdev = &flash->led_cdev;
|
||||
u32 sources[SY7802_MAX_LEDS];
|
||||
int i, num, ret;
|
||||
|
||||
num = of_property_count_u32_elems(np, "led-sources");
|
||||
if (num < 1) {
|
||||
dev_err(dev, "Not specified or wrong number of led-sources\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32_array(np, "led-sources", sources, num);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (sources[i] >= SY7802_MAX_LEDS)
|
||||
return -EINVAL;
|
||||
if (led->chip->leds_active & BIT(sources[i]))
|
||||
return -EINVAL;
|
||||
led->chip->leds_active |= BIT(sources[i]);
|
||||
}
|
||||
|
||||
/* If both channels are specified in 'led-sources', joint flash output mode is used */
|
||||
led->led_id = num == 2 ? SY7802_LED_JOINT : sources[0];
|
||||
|
||||
lcdev->max_brightness = SY7802_TORCH_BRIGHTNESS_MAX;
|
||||
lcdev->brightness_set_blocking = sy7802_torch_brightness_set;
|
||||
lcdev->flags |= LED_DEV_CAP_FLASH;
|
||||
|
||||
flash->ops = &sy7802_flash_ops;
|
||||
|
||||
sy7802_init_flash_brightness(flash);
|
||||
sy7802_init_flash_timeout(flash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sy7802_chip_check(struct sy7802 *chip)
|
||||
{
|
||||
struct device *dev = chip->dev;
|
||||
u32 chipid;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(chip->regmap, SY7802_REG_DEV_ID, &chipid);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to read chip ID\n");
|
||||
|
||||
if (chipid != SY7802_CHIP_ID)
|
||||
return dev_err_probe(dev, -ENODEV, "Unsupported chip detected: %x\n", chipid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sy7802_enable(struct sy7802 *chip)
|
||||
{
|
||||
gpiod_set_value_cansleep(chip->enable_gpio, 1);
|
||||
usleep_range(200, 300);
|
||||
}
|
||||
|
||||
static void sy7802_disable(struct sy7802 *chip)
|
||||
{
|
||||
gpiod_set_value_cansleep(chip->enable_gpio, 0);
|
||||
}
|
||||
|
||||
static int sy7802_probe_dt(struct sy7802 *chip)
|
||||
{
|
||||
struct device_node *np = dev_of_node(chip->dev);
|
||||
int child_num;
|
||||
int ret;
|
||||
|
||||
regmap_write(chip->regmap, SY7802_REG_ENABLE, SY7802_MODE_OFF);
|
||||
regmap_write(chip->regmap, SY7802_REG_TORCH_BRIGHTNESS, LED_OFF);
|
||||
|
||||
child_num = 0;
|
||||
for_each_available_child_of_node_scoped(np, child) {
|
||||
struct sy7802_led *led = chip->leds + child_num;
|
||||
|
||||
led->chip = chip;
|
||||
led->led_id = child_num;
|
||||
|
||||
ret = sy7802_init_flash_properties(chip->dev, led, child);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = sy7802_led_register(chip->dev, led, child);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
child_num++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sy7802_chip_disable_action(void *data)
|
||||
{
|
||||
struct sy7802 *chip = data;
|
||||
|
||||
sy7802_disable(chip);
|
||||
}
|
||||
|
||||
static void sy7802_regulator_disable_action(void *data)
|
||||
{
|
||||
struct sy7802 *chip = data;
|
||||
|
||||
regulator_disable(chip->vin_regulator);
|
||||
}
|
||||
|
||||
static const struct regmap_config sy7802_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 0xff,
|
||||
.cache_type = REGCACHE_MAPLE,
|
||||
.reg_defaults = sy7802_regmap_defs,
|
||||
.num_reg_defaults = ARRAY_SIZE(sy7802_regmap_defs),
|
||||
};
|
||||
|
||||
static int sy7802_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct sy7802 *chip;
|
||||
size_t count;
|
||||
int ret;
|
||||
|
||||
count = device_get_child_node_count(dev);
|
||||
if (!count || count > SY7802_MAX_LEDS)
|
||||
return dev_err_probe(dev, -EINVAL, "Invalid amount of LED nodes %zu\n", count);
|
||||
|
||||
chip = devm_kzalloc(dev, struct_size(chip, leds, count), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->num_leds = count;
|
||||
|
||||
chip->dev = dev;
|
||||
i2c_set_clientdata(client, chip);
|
||||
|
||||
chip->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
|
||||
ret = PTR_ERR_OR_ZERO(chip->enable_gpio);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to request enable gpio\n");
|
||||
|
||||
chip->vin_regulator = devm_regulator_get(dev, "vin");
|
||||
ret = PTR_ERR_OR_ZERO(chip->vin_regulator);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to request regulator\n");
|
||||
|
||||
ret = regulator_enable(chip->vin_regulator);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to enable regulator\n");
|
||||
|
||||
ret = devm_add_action_or_reset(dev, sy7802_regulator_disable_action, chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_mutex_init(dev, &chip->mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&chip->mutex);
|
||||
|
||||
chip->regmap = devm_regmap_init_i2c(client, &sy7802_regmap_config);
|
||||
if (IS_ERR(chip->regmap)) {
|
||||
ret = PTR_ERR(chip->regmap);
|
||||
dev_err_probe(dev, ret, "Failed to allocate register map\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = sy7802_probe_dt(chip);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
sy7802_enable(chip);
|
||||
|
||||
ret = devm_add_action_or_reset(dev, sy7802_chip_disable_action, chip);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = sy7802_chip_check(chip);
|
||||
|
||||
error:
|
||||
mutex_unlock(&chip->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id __maybe_unused sy7802_leds_match[] = {
|
||||
{ .compatible = "silergy,sy7802", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sy7802_leds_match);
|
||||
|
||||
static struct i2c_driver sy7802_driver = {
|
||||
.driver = {
|
||||
.name = "sy7802",
|
||||
.of_match_table = of_match_ptr(sy7802_leds_match),
|
||||
},
|
||||
.probe = sy7802_probe,
|
||||
};
|
||||
module_i2c_driver(sy7802_driver);
|
||||
|
||||
MODULE_AUTHOR("André Apitzsch <git@apitzsch.eu>");
|
||||
MODULE_DESCRIPTION("Silergy SY7802 flash LED driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
Loading…
Reference in New Issue