1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Silergy SY7802 flash LED driver with an I2C interface 4 * 5 * Copyright 2024 André Apitzsch <git@apitzsch.eu> 6 */ 7 8 #include <linux/gpio/consumer.h> 9 #include <linux/i2c.h> 10 #include <linux/kernel.h> 11 #include <linux/led-class-flash.h> 12 #include <linux/module.h> 13 #include <linux/mutex.h> 14 #include <linux/regmap.h> 15 #include <linux/regulator/consumer.h> 16 17 #define SY7802_MAX_LEDS 2 18 #define SY7802_LED_JOINT 2 19 20 #define SY7802_REG_ENABLE 0x10 21 #define SY7802_REG_TORCH_BRIGHTNESS 0xa0 22 #define SY7802_REG_FLASH_BRIGHTNESS 0xb0 23 #define SY7802_REG_FLASH_DURATION 0xc0 24 #define SY7802_REG_FLAGS 0xd0 25 #define SY7802_REG_CONFIG_1 0xe0 26 #define SY7802_REG_CONFIG_2 0xf0 27 #define SY7802_REG_VIN_MONITOR 0x80 28 #define SY7802_REG_LAST_FLASH 0x81 29 #define SY7802_REG_VLED_MONITOR 0x30 30 #define SY7802_REG_ADC_DELAY 0x31 31 #define SY7802_REG_DEV_ID 0xff 32 33 #define SY7802_MODE_OFF 0 34 #define SY7802_MODE_TORCH 2 35 #define SY7802_MODE_FLASH 3 36 #define SY7802_MODE_MASK GENMASK(1, 0) 37 38 #define SY7802_LEDS_SHIFT 3 39 #define SY7802_LEDS_MASK(_id) (BIT(_id) << SY7802_LEDS_SHIFT) 40 #define SY7802_LEDS_MASK_ALL (SY7802_LEDS_MASK(0) | SY7802_LEDS_MASK(1)) 41 42 #define SY7802_TORCH_CURRENT_SHIFT 3 43 #define SY7802_TORCH_CURRENT_MASK(_id) \ 44 (GENMASK(2, 0) << (SY7802_TORCH_CURRENT_SHIFT * (_id))) 45 #define SY7802_TORCH_CURRENT_MASK_ALL \ 46 (SY7802_TORCH_CURRENT_MASK(0) | SY7802_TORCH_CURRENT_MASK(1)) 47 48 #define SY7802_FLASH_CURRENT_SHIFT 4 49 #define SY7802_FLASH_CURRENT_MASK(_id) \ 50 (GENMASK(3, 0) << (SY7802_FLASH_CURRENT_SHIFT * (_id))) 51 #define SY7802_FLASH_CURRENT_MASK_ALL \ 52 (SY7802_FLASH_CURRENT_MASK(0) | SY7802_FLASH_CURRENT_MASK(1)) 53 54 #define SY7802_TIMEOUT_DEFAULT_US 512000U 55 #define SY7802_TIMEOUT_MIN_US 32000U 56 #define SY7802_TIMEOUT_MAX_US 1024000U 57 #define SY7802_TIMEOUT_STEPSIZE_US 32000U 58 59 #define SY7802_TORCH_BRIGHTNESS_MAX 8 60 61 #define SY7802_FLASH_BRIGHTNESS_DEFAULT 14 62 #define SY7802_FLASH_BRIGHTNESS_MIN 0 63 #define SY7802_FLASH_BRIGHTNESS_MAX 15 64 #define SY7802_FLASH_BRIGHTNESS_STEP 1 65 66 #define SY7802_FLAG_TIMEOUT BIT(0) 67 #define SY7802_FLAG_THERMAL_SHUTDOWN BIT(1) 68 #define SY7802_FLAG_LED_FAULT BIT(2) 69 #define SY7802_FLAG_TX1_INTERRUPT BIT(3) 70 #define SY7802_FLAG_TX2_INTERRUPT BIT(4) 71 #define SY7802_FLAG_LED_THERMAL_FAULT BIT(5) 72 #define SY7802_FLAG_FLASH_INPUT_VOLTAGE_LOW BIT(6) 73 #define SY7802_FLAG_INPUT_VOLTAGE_LOW BIT(7) 74 75 #define SY7802_CHIP_ID 0x51 76 77 static const struct reg_default sy7802_regmap_defs[] = { 78 { SY7802_REG_ENABLE, SY7802_LEDS_MASK_ALL }, 79 { SY7802_REG_TORCH_BRIGHTNESS, 0x92 }, 80 { SY7802_REG_FLASH_BRIGHTNESS, SY7802_FLASH_BRIGHTNESS_DEFAULT | 81 SY7802_FLASH_BRIGHTNESS_DEFAULT << SY7802_FLASH_CURRENT_SHIFT }, 82 { SY7802_REG_FLASH_DURATION, 0x6f }, 83 { SY7802_REG_FLAGS, 0x0 }, 84 { SY7802_REG_CONFIG_1, 0x68 }, 85 { SY7802_REG_CONFIG_2, 0xf0 }, 86 }; 87 88 struct sy7802_led { 89 struct led_classdev_flash flash; 90 struct sy7802 *chip; 91 u8 led_id; 92 }; 93 94 struct sy7802 { 95 struct device *dev; 96 struct regmap *regmap; 97 struct mutex mutex; 98 99 struct gpio_desc *enable_gpio; 100 struct regulator *vin_regulator; 101 102 unsigned int fled_strobe_used; 103 unsigned int fled_torch_used; 104 unsigned int leds_active; 105 int num_leds; 106 struct sy7802_led leds[] __counted_by(num_leds); 107 }; 108 109 static int sy7802_torch_brightness_set(struct led_classdev *lcdev, enum led_brightness brightness) 110 { 111 struct sy7802_led *led = container_of(lcdev, struct sy7802_led, flash.led_cdev); 112 struct sy7802 *chip = led->chip; 113 u32 fled_torch_used_tmp; 114 u32 led_enable_mask; 115 u32 enable_mask; 116 u32 torch_mask; 117 u32 val; 118 int ret; 119 120 mutex_lock(&chip->mutex); 121 122 if (chip->fled_strobe_used) { 123 dev_warn(chip->dev, "Cannot set torch brightness whilst strobe is enabled\n"); 124 ret = -EBUSY; 125 goto unlock; 126 } 127 128 if (brightness) 129 fled_torch_used_tmp = chip->fled_torch_used | BIT(led->led_id); 130 else 131 fled_torch_used_tmp = chip->fled_torch_used & ~BIT(led->led_id); 132 133 led_enable_mask = led->led_id == SY7802_LED_JOINT ? 134 SY7802_LEDS_MASK_ALL : 135 SY7802_LEDS_MASK(led->led_id); 136 137 val = brightness ? led_enable_mask : SY7802_MODE_OFF; 138 if (fled_torch_used_tmp) 139 val |= SY7802_MODE_TORCH; 140 141 /* Disable torch to apply brightness */ 142 ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, SY7802_MODE_MASK, 143 SY7802_MODE_OFF); 144 if (ret) 145 goto unlock; 146 147 torch_mask = led->led_id == SY7802_LED_JOINT ? 148 SY7802_TORCH_CURRENT_MASK_ALL : 149 SY7802_TORCH_CURRENT_MASK(led->led_id); 150 151 /* Register expects brightness between 0 and MAX_BRIGHTNESS - 1 */ 152 if (brightness) 153 brightness -= 1; 154 155 brightness |= (brightness << SY7802_TORCH_CURRENT_SHIFT); 156 157 ret = regmap_update_bits(chip->regmap, SY7802_REG_TORCH_BRIGHTNESS, torch_mask, brightness); 158 if (ret) 159 goto unlock; 160 161 enable_mask = SY7802_MODE_MASK | led_enable_mask; 162 ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, enable_mask, val); 163 if (ret) 164 goto unlock; 165 166 chip->fled_torch_used = fled_torch_used_tmp; 167 168 unlock: 169 mutex_unlock(&chip->mutex); 170 return ret; 171 } 172 173 static int sy7802_flash_brightness_set(struct led_classdev_flash *fl_cdev, u32 brightness) 174 { 175 struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash); 176 struct led_flash_setting *s = &fl_cdev->brightness; 177 u32 val = (brightness - s->min) / s->step; 178 struct sy7802 *chip = led->chip; 179 u32 flash_mask; 180 int ret; 181 182 val |= (val << SY7802_FLASH_CURRENT_SHIFT); 183 flash_mask = led->led_id == SY7802_LED_JOINT ? 184 SY7802_FLASH_CURRENT_MASK_ALL : 185 SY7802_FLASH_CURRENT_MASK(led->led_id); 186 187 mutex_lock(&chip->mutex); 188 ret = regmap_update_bits(chip->regmap, SY7802_REG_FLASH_BRIGHTNESS, flash_mask, val); 189 mutex_unlock(&chip->mutex); 190 191 return ret; 192 } 193 194 static int sy7802_strobe_set(struct led_classdev_flash *fl_cdev, bool state) 195 { 196 struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash); 197 struct sy7802 *chip = led->chip; 198 u32 fled_strobe_used_tmp; 199 u32 led_enable_mask; 200 u32 enable_mask; 201 u32 val; 202 int ret; 203 204 mutex_lock(&chip->mutex); 205 206 if (chip->fled_torch_used) { 207 dev_warn(chip->dev, "Cannot set strobe brightness whilst torch is enabled\n"); 208 ret = -EBUSY; 209 goto unlock; 210 } 211 212 if (state) 213 fled_strobe_used_tmp = chip->fled_strobe_used | BIT(led->led_id); 214 else 215 fled_strobe_used_tmp = chip->fled_strobe_used & ~BIT(led->led_id); 216 217 led_enable_mask = led->led_id == SY7802_LED_JOINT ? 218 SY7802_LEDS_MASK_ALL : 219 SY7802_LEDS_MASK(led->led_id); 220 221 val = state ? led_enable_mask : SY7802_MODE_OFF; 222 if (fled_strobe_used_tmp) 223 val |= SY7802_MODE_FLASH; 224 225 enable_mask = SY7802_MODE_MASK | led_enable_mask; 226 ret = regmap_update_bits(chip->regmap, SY7802_REG_ENABLE, enable_mask, val); 227 228 if (ret) 229 goto unlock; 230 231 chip->fled_strobe_used = fled_strobe_used_tmp; 232 233 unlock: 234 mutex_unlock(&chip->mutex); 235 return ret; 236 } 237 238 static int sy7802_strobe_get(struct led_classdev_flash *fl_cdev, bool *state) 239 { 240 struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash); 241 struct sy7802 *chip = led->chip; 242 243 mutex_lock(&chip->mutex); 244 *state = !!(chip->fled_strobe_used & BIT(led->led_id)); 245 mutex_unlock(&chip->mutex); 246 247 return 0; 248 } 249 250 static int sy7802_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout) 251 { 252 struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash); 253 struct led_flash_setting *s = &fl_cdev->timeout; 254 u32 val = (timeout - s->min) / s->step; 255 struct sy7802 *chip = led->chip; 256 257 return regmap_write(chip->regmap, SY7802_REG_FLASH_DURATION, val); 258 } 259 260 static int sy7802_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault) 261 { 262 struct sy7802_led *led = container_of(fl_cdev, struct sy7802_led, flash); 263 struct sy7802 *chip = led->chip; 264 u32 val, led_faults = 0; 265 int ret; 266 267 /* NOTE: reading register clears fault status */ 268 ret = regmap_read(chip->regmap, SY7802_REG_FLAGS, &val); 269 if (ret) 270 return ret; 271 272 if (val & (SY7802_FLAG_FLASH_INPUT_VOLTAGE_LOW | SY7802_FLAG_INPUT_VOLTAGE_LOW)) 273 led_faults |= LED_FAULT_INPUT_VOLTAGE; 274 275 if (val & SY7802_FLAG_THERMAL_SHUTDOWN) 276 led_faults |= LED_FAULT_OVER_TEMPERATURE; 277 278 if (val & SY7802_FLAG_TIMEOUT) 279 led_faults |= LED_FAULT_TIMEOUT; 280 281 *fault = led_faults; 282 return 0; 283 } 284 285 static const struct led_flash_ops sy7802_flash_ops = { 286 .flash_brightness_set = sy7802_flash_brightness_set, 287 .strobe_set = sy7802_strobe_set, 288 .strobe_get = sy7802_strobe_get, 289 .timeout_set = sy7802_timeout_set, 290 .fault_get = sy7802_fault_get, 291 }; 292 293 static void sy7802_init_flash_brightness(struct led_classdev_flash *fl_cdev) 294 { 295 struct led_flash_setting *s; 296 297 /* Init flash brightness setting */ 298 s = &fl_cdev->brightness; 299 s->min = SY7802_FLASH_BRIGHTNESS_MIN; 300 s->max = SY7802_FLASH_BRIGHTNESS_MAX; 301 s->step = SY7802_FLASH_BRIGHTNESS_STEP; 302 s->val = SY7802_FLASH_BRIGHTNESS_DEFAULT; 303 } 304 305 static void sy7802_init_flash_timeout(struct led_classdev_flash *fl_cdev) 306 { 307 struct led_flash_setting *s; 308 309 /* Init flash timeout setting */ 310 s = &fl_cdev->timeout; 311 s->min = SY7802_TIMEOUT_MIN_US; 312 s->max = SY7802_TIMEOUT_MAX_US; 313 s->step = SY7802_TIMEOUT_STEPSIZE_US; 314 s->val = SY7802_TIMEOUT_DEFAULT_US; 315 } 316 317 static int sy7802_led_register(struct device *dev, struct sy7802_led *led, 318 struct device_node *np) 319 { 320 struct led_init_data init_data = {}; 321 int ret; 322 323 init_data.fwnode = of_fwnode_handle(np); 324 325 ret = devm_led_classdev_flash_register_ext(dev, &led->flash, &init_data); 326 if (ret) { 327 dev_err(dev, "Couldn't register flash %d\n", led->led_id); 328 return ret; 329 } 330 331 return 0; 332 } 333 334 static int sy7802_init_flash_properties(struct device *dev, struct sy7802_led *led, 335 struct device_node *np) 336 { 337 struct led_classdev_flash *flash = &led->flash; 338 struct led_classdev *lcdev = &flash->led_cdev; 339 u32 sources[SY7802_MAX_LEDS]; 340 int i, num, ret; 341 342 num = of_property_count_u32_elems(np, "led-sources"); 343 if (num < 1) { 344 dev_err(dev, "Not specified or wrong number of led-sources\n"); 345 return -EINVAL; 346 } 347 348 ret = of_property_read_u32_array(np, "led-sources", sources, num); 349 if (ret) 350 return ret; 351 352 for (i = 0; i < num; i++) { 353 if (sources[i] >= SY7802_MAX_LEDS) 354 return -EINVAL; 355 if (led->chip->leds_active & BIT(sources[i])) 356 return -EINVAL; 357 led->chip->leds_active |= BIT(sources[i]); 358 } 359 360 /* If both channels are specified in 'led-sources', joint flash output mode is used */ 361 led->led_id = num == 2 ? SY7802_LED_JOINT : sources[0]; 362 363 lcdev->max_brightness = SY7802_TORCH_BRIGHTNESS_MAX; 364 lcdev->brightness_set_blocking = sy7802_torch_brightness_set; 365 lcdev->flags |= LED_DEV_CAP_FLASH; 366 367 flash->ops = &sy7802_flash_ops; 368 369 sy7802_init_flash_brightness(flash); 370 sy7802_init_flash_timeout(flash); 371 372 return 0; 373 } 374 375 static int sy7802_chip_check(struct sy7802 *chip) 376 { 377 struct device *dev = chip->dev; 378 u32 chipid; 379 int ret; 380 381 ret = regmap_read(chip->regmap, SY7802_REG_DEV_ID, &chipid); 382 if (ret) 383 return dev_err_probe(dev, ret, "Failed to read chip ID\n"); 384 385 if (chipid != SY7802_CHIP_ID) 386 return dev_err_probe(dev, -ENODEV, "Unsupported chip detected: %x\n", chipid); 387 388 return 0; 389 } 390 391 static void sy7802_enable(struct sy7802 *chip) 392 { 393 gpiod_set_value_cansleep(chip->enable_gpio, 1); 394 usleep_range(200, 300); 395 } 396 397 static void sy7802_disable(struct sy7802 *chip) 398 { 399 gpiod_set_value_cansleep(chip->enable_gpio, 0); 400 } 401 402 static int sy7802_probe_dt(struct sy7802 *chip) 403 { 404 struct device_node *np = dev_of_node(chip->dev); 405 int child_num; 406 int ret; 407 408 regmap_write(chip->regmap, SY7802_REG_ENABLE, SY7802_MODE_OFF); 409 regmap_write(chip->regmap, SY7802_REG_TORCH_BRIGHTNESS, LED_OFF); 410 411 child_num = 0; 412 for_each_available_child_of_node_scoped(np, child) { 413 struct sy7802_led *led = chip->leds + child_num; 414 415 led->chip = chip; 416 led->led_id = child_num; 417 418 ret = sy7802_init_flash_properties(chip->dev, led, child); 419 if (ret) 420 return ret; 421 422 ret = sy7802_led_register(chip->dev, led, child); 423 if (ret) 424 return ret; 425 426 child_num++; 427 } 428 return 0; 429 } 430 431 static void sy7802_chip_disable_action(void *data) 432 { 433 struct sy7802 *chip = data; 434 435 sy7802_disable(chip); 436 } 437 438 static void sy7802_regulator_disable_action(void *data) 439 { 440 struct sy7802 *chip = data; 441 442 regulator_disable(chip->vin_regulator); 443 } 444 445 static const struct regmap_config sy7802_regmap_config = { 446 .reg_bits = 8, 447 .val_bits = 8, 448 .max_register = 0xff, 449 .cache_type = REGCACHE_MAPLE, 450 .reg_defaults = sy7802_regmap_defs, 451 .num_reg_defaults = ARRAY_SIZE(sy7802_regmap_defs), 452 }; 453 454 static int sy7802_probe(struct i2c_client *client) 455 { 456 struct device *dev = &client->dev; 457 struct sy7802 *chip; 458 size_t count; 459 int ret; 460 461 count = device_get_child_node_count(dev); 462 if (!count || count > SY7802_MAX_LEDS) 463 return dev_err_probe(dev, -EINVAL, "Invalid amount of LED nodes %zu\n", count); 464 465 chip = devm_kzalloc(dev, struct_size(chip, leds, count), GFP_KERNEL); 466 if (!chip) 467 return -ENOMEM; 468 469 chip->num_leds = count; 470 471 chip->dev = dev; 472 i2c_set_clientdata(client, chip); 473 474 chip->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); 475 ret = PTR_ERR_OR_ZERO(chip->enable_gpio); 476 if (ret) 477 return dev_err_probe(dev, ret, "Failed to request enable gpio\n"); 478 479 chip->vin_regulator = devm_regulator_get(dev, "vin"); 480 ret = PTR_ERR_OR_ZERO(chip->vin_regulator); 481 if (ret) 482 return dev_err_probe(dev, ret, "Failed to request regulator\n"); 483 484 ret = regulator_enable(chip->vin_regulator); 485 if (ret) 486 return dev_err_probe(dev, ret, "Failed to enable regulator\n"); 487 488 ret = devm_add_action_or_reset(dev, sy7802_regulator_disable_action, chip); 489 if (ret) 490 return ret; 491 492 ret = devm_mutex_init(dev, &chip->mutex); 493 if (ret) 494 return ret; 495 496 mutex_lock(&chip->mutex); 497 498 chip->regmap = devm_regmap_init_i2c(client, &sy7802_regmap_config); 499 if (IS_ERR(chip->regmap)) { 500 ret = PTR_ERR(chip->regmap); 501 dev_err_probe(dev, ret, "Failed to allocate register map\n"); 502 goto error; 503 } 504 505 ret = sy7802_probe_dt(chip); 506 if (ret < 0) 507 goto error; 508 509 sy7802_enable(chip); 510 511 ret = devm_add_action_or_reset(dev, sy7802_chip_disable_action, chip); 512 if (ret) 513 goto error; 514 515 ret = sy7802_chip_check(chip); 516 517 error: 518 mutex_unlock(&chip->mutex); 519 return ret; 520 } 521 522 static const struct of_device_id __maybe_unused sy7802_leds_match[] = { 523 { .compatible = "silergy,sy7802", }, 524 {} 525 }; 526 MODULE_DEVICE_TABLE(of, sy7802_leds_match); 527 528 static struct i2c_driver sy7802_driver = { 529 .driver = { 530 .name = "sy7802", 531 .of_match_table = of_match_ptr(sy7802_leds_match), 532 }, 533 .probe = sy7802_probe, 534 }; 535 module_i2c_driver(sy7802_driver); 536 537 MODULE_AUTHOR("André Apitzsch <git@apitzsch.eu>"); 538 MODULE_DESCRIPTION("Silergy SY7802 flash LED driver"); 539 MODULE_LICENSE("GPL"); 540