Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'leds-next-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds

Pull LED updates from Lee Jones:
"LED Triggers:
- Allow writing "default" to the sysfs 'trigger' attribute to set an
LED to its default trigger
- If the default trigger is "none", writing "default" will remove the
current trigger
- Updated sysfs ABI documentation for the new "default" trigger
functionality

LED KUnit Testing:
- Provide a skeleton KUnit test suite for the LEDs framework
- Expand the LED class device registration KUnit test to cover more
scenarios, including 'brightness_get' behavior
- Add KUnit tests for the LED lookup and get API ('led_add_lookup',
'devm_led_get')

LED Flash Class:
- Add support for setting flash/strobe duration through a new
'duration_set' op and 'led_set_flash_duration()' function, aligning
with 'V4L2_CID_FLASH_DURATION'

Texas Instruments TPS6131x:
- Add a new driver for the TPS61310/TPS61311 flash LED controllers
- The driver supports the device's three constant-current sinks for
flash and torch modes

LED Core:
- Prevent potential 'snprintf()' truncations in LED names by checking
for buffer overflows

ChromeOS EC LEDs:
- Avoid a -Wflex-array-member-not-at-end GCC warning by replacing an
on-stack flexible structure definition with a utility function call

Multicolor LEDs:
- Fix issue where setting multi_intensity while software blinking is
active could stop blinking

PCA955x LEDs:
- Avoid potential buffer overflow when creating default labels by
changing a field's type to 'u8' and updating format specifiers

PCA995x LEDs:
- Fix a typo (stray space) in an 'of_device_id' entry in the
'pca995x_of_match' table

Kconfig:
- Prevent LED drivers from being enabled by default when
'COMPILE_TEST' is set

Device Property API:
- Split 'device_get_child_node_count()' into a new helper
'fwnode_get_child_node_count()' that doesn't require a device
struct, making the API more symmetrical

Driver Modernization (using 'fwnode_get_child_node_count()'):
- Update 'leds-pwm-multicolor', 'leds-ncp5623' and 'leds-ncp5623' to
use the new 'fwnode_get_child_node_count()' helper, removing their
custom implementation
- As above in the USB Type-C TCPM driver

Driver Modernization (using new GPIO setter callbacks):
- Convert 'leds-lgm-sso' to use new GPIO line value setter callbacks
which return an integer for error handling
- Convert 'leds-pca955x', 'leds-pca9532' and 'leds-tca6507' to use
new GPIO setter callbacks

Documentation:
- Remove the '.rst' extension for 'leds-st1202' in the documentation
index for consistency

LP8860 LEDs:
- Use 'regmap_multi_reg_write()' for EEPROM writes instead of manual
looping
- Use scoped mutex guards and 'devm_mutex_init()' to simplify
function exits and ensure automatic cleanup
- Remove default register definitions that are unused when regmap
caching is not active
- Use 'devm_regulator_get_enable_optional()' to handle the optional
regulator, simplifying enabling and removing manual disabling
- Refactor 'lp8860_unlock_eeprom()' to only perform the unlock
operation, removing the lock part and an unnecessary parameter
- Use a 'devm' action to disable the enable-GPIO, simplifying cleanup
and error paths, and remove the now-empty '.remove()' function

Turris Omnia LEDs:
- Drop unnecessary commas in terminator entries of 'struct attribute'
and 'struct of_device_id' arrays

MT6370 RGB LEDs:
- Use the 'LINEAR_RANGE()' for defining 'struct linear_range' entries
to improve robustness

Texas Instruments TPS6131x:
- Add new devicetree bindings for the TI TPS61310/TPS61311 flash LED
driver"

* tag 'leds-next-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds: (31 commits)
leds: tps6131x: Add support for Texas Instruments TPS6131X flash LED driver
dt-bindings: leds: Add Texas Instruments TPS6131x flash LED driver
leds: flash: Add support for flash/strobe duration
leds: rgb: leds-mt6370-rgb: Improve definition of some struct linear_range
leds: led-test: Provide tests for the lookup and get infrastructure
leds: led-test: Fill out the registration test to cover more test cases
leds: led-test: Remove standard error checking after KUNIT_ASSERT_*()
leds: pca995x: Fix typo in pca995x_of_match's of_device_id entry
leds: Provide skeleton KUnit testing for the LEDs framework
leds: tca6507: Use new GPIO line value setter callbacks
leds: pca9532: Use new GPIO line value setter callbacks
leds: pca955x: Use new GPIO line value setter callbacks
leds: lgm-sso: Use new GPIO line value setter callbacks
leds: Do not enable by default during compile testing
leds: turris-omnia: Drop commas in the terminator entries
leds: lp8860: Disable GPIO with devm action
leds: lp8860: Only unlock in lp8860_unlock_eeprom()
leds: lp8860: Enable regulator using enable_optional helper
leds: lp8860: Remove default regs when not caching
leds: lp8860: Use new mutex guards to cleanup function exits
...

+1289 -259
+6
Documentation/ABI/testing/sysfs-class-led
··· 72 72 /sys/class/leds/<led> once a given trigger is selected. For 73 73 their documentation see `sysfs-class-led-trigger-*`. 74 74 75 + Writing "none" removes the trigger for this LED. 76 + 77 + Writing "default" sets the trigger to the LED's default trigger 78 + (which would often be configured in the device tree for the 79 + hardware). 80 + 75 81 What: /sys/class/leds/<led>/inverted 76 82 Date: January 2011 77 83 KernelVersion: 2.6.38
+120
Documentation/devicetree/bindings/leds/ti,tps61310.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/leds/ti,tps61310.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Texas Instruments TPS6131X flash LED driver 8 + 9 + maintainers: 10 + - Matthias Fend <matthias.fend@emfend.at> 11 + 12 + description: | 13 + The TPS61310/TPS61311 is a flash LED driver with I2C interface. 14 + Its power stage is capable of supplying a maximum total current of roughly 1500mA. 15 + The TPS6131x provides three constant-current sinks, capable of sinking 16 + up to 2 x 400mA (LED1 and LED3) and 800mA (LED2) in flash mode. 17 + In torch mode, each sink (LED1, LED2, LED3) supports currents up to 175mA. 18 + Since the three current sinks share most of the control components such as 19 + flash timer, control logic, safety timer and the operating mode, they cannot 20 + be used completely independently of each other. Therefore, only one LED is 21 + supported, but the current sinks can be combined accordingly. 22 + 23 + The data sheet can be found at: 24 + https://www.ti.com/lit/ds/symlink/tps61310.pdf 25 + 26 + properties: 27 + compatible: 28 + oneOf: 29 + - items: 30 + - enum: 31 + - ti,tps61311 32 + - const: ti,tps61310 33 + - items: 34 + - const: ti,tps61310 35 + 36 + reg: 37 + maxItems: 1 38 + 39 + reset-gpios: 40 + maxItems: 1 41 + description: GPIO connected to NRESET pin 42 + 43 + ti,valley-current-limit: 44 + type: boolean 45 + description: 46 + Reduce the valley peak current limit from 1750mA to 1250mA (TPS61310) or 47 + from 2480mA to 1800mA (TPS61311). 48 + 49 + led: 50 + type: object 51 + $ref: common.yaml# 52 + unevaluatedProperties: false 53 + 54 + properties: 55 + led-sources: 56 + minItems: 1 57 + maxItems: 3 58 + items: 59 + enum: [1, 2, 3] 60 + 61 + led-max-microamp: 62 + oneOf: 63 + - minimum: 50000 64 + maximum: 350000 65 + multipleOf: 50000 66 + - minimum: 25000 67 + maximum: 525000 68 + multipleOf: 25000 69 + 70 + flash-max-microamp: 71 + oneOf: 72 + - minimum: 50000 73 + maximum: 800000 74 + multipleOf: 50000 75 + - minimum: 25000 76 + maximum: 1500000 77 + multipleOf: 25000 78 + 79 + flash-max-timeout-us: 80 + enum: [ 5300, 10700, 16000, 21300, 26600, 32000, 37300, 68200, 71500, 81 + 102200, 136300, 170400, 204500, 340800, 579300, 852000 ] 82 + 83 + required: 84 + - led-sources 85 + - led-max-microamp 86 + - flash-max-microamp 87 + - flash-max-timeout-us 88 + 89 + required: 90 + - compatible 91 + - reg 92 + - led 93 + 94 + additionalProperties: false 95 + 96 + examples: 97 + - | 98 + #include <dt-bindings/leds/common.h> 99 + #include <dt-bindings/gpio/gpio.h> 100 + 101 + i2c { 102 + #address-cells = <1>; 103 + #size-cells = <0>; 104 + 105 + led-controller@33 { 106 + compatible = "ti,tps61311", "ti,tps61310"; 107 + reg = <0x33>; 108 + 109 + reset-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; 110 + 111 + led { 112 + function = LED_FUNCTION_FLASH; 113 + color = <LED_COLOR_ID_WHITE>; 114 + led-sources = <1>, <2>, <3>; 115 + led-max-microamp = <525000>; 116 + flash-max-microamp = <1500000>; 117 + flash-max-timeout-us = <852000>; 118 + }; 119 + }; 120 + };
+1 -1
Documentation/leds/index.rst
··· 28 28 leds-mlxcpld 29 29 leds-mt6370-rgb 30 30 leds-sc27xx 31 - leds-st1202.rst 31 + leds-st1202 32 32 leds-qcom-lpg
+7
MAINTAINERS
··· 24447 24447 F: Documentation/hwmon/tps23861.rst 24448 24448 F: drivers/hwmon/tps23861.c 24449 24449 24450 + TEXAS INSTRUMENTS TPS6131X FLASH LED DRIVER 24451 + M: Matthias Fend <matthias.fend@emfend.at> 24452 + L: linux-leds@vger.kernel.org 24453 + S: Maintained 24454 + F: Documentation/devicetree/bindings/leds/ti,tps6131x.yaml 24455 + F: drivers/leds/flash/leds-tps6131x.c 24456 + 24450 24457 TEXAS INSTRUMENTS' DAC7612 DAC DRIVER 24451 24458 M: Ricardo Ribalda <ribalda@kernel.org> 24452 24459 L: linux-iio@vger.kernel.org
+6 -6
drivers/base/property.c
··· 928 928 EXPORT_SYMBOL_GPL(fwnode_device_is_available); 929 929 930 930 /** 931 - * device_get_child_node_count - return the number of child nodes for device 932 - * @dev: Device to count the child nodes for 931 + * fwnode_get_child_node_count - return the number of child nodes for a given firmware node 932 + * @fwnode: Pointer to the parent firmware node 933 933 * 934 - * Return: the number of child nodes for a given device. 934 + * Return: the number of child nodes for a given firmware node. 935 935 */ 936 - unsigned int device_get_child_node_count(const struct device *dev) 936 + unsigned int fwnode_get_child_node_count(const struct fwnode_handle *fwnode) 937 937 { 938 938 struct fwnode_handle *child; 939 939 unsigned int count = 0; 940 940 941 - device_for_each_child_node(dev, child) 941 + fwnode_for_each_child_node(fwnode, child) 942 942 count++; 943 943 944 944 return count; 945 945 } 946 - EXPORT_SYMBOL_GPL(device_get_child_node_count); 946 + EXPORT_SYMBOL_GPL(fwnode_get_child_node_count); 947 947 948 948 bool device_dma_supported(const struct device *dev) 949 949 {
+4
drivers/leds/.kunitconfig
··· 1 + CONFIG_KUNIT=y 2 + CONFIG_NEW_LEDS=y 3 + CONFIG_LEDS_CLASS=y 4 + CONFIG_LEDS_KUNIT_TEST=y
+9 -2
drivers/leds/Kconfig
··· 55 55 56 56 See Documentation/ABI/testing/sysfs-class-led for details. 57 57 58 + config LEDS_KUNIT_TEST 59 + tristate "KUnit tests for LEDs" 60 + depends on KUNIT && LEDS_CLASS 61 + default KUNIT_ALL_TESTS 62 + help 63 + Say Y here to enable KUnit testing for the LEDs framework. 64 + 58 65 comment "LED drivers" 59 66 60 67 config LEDS_88PM860X ··· 742 735 tristate "LED support for Network Space v2 GPIO LEDs" 743 736 depends on LEDS_CLASS 744 737 depends on MACH_KIRKWOOD || MACH_ARMADA_370 || COMPILE_TEST 745 - default y 738 + default y if MACH_KIRKWOOD || MACH_ARMADA_370 746 739 help 747 740 This option enables support for the dual-GPIO LEDs found on the 748 741 following LaCie/Seagate boards: ··· 757 750 depends on LEDS_CLASS 758 751 depends on MACH_KIRKWOOD || COMPILE_TEST 759 752 depends on OF_GPIO 760 - default y 753 + default MACH_KIRKWOOD 761 754 help 762 755 This option enables support for LEDs found on the LaCie 2Big 763 756 and 5Big Network v2 boards. The LEDs are wired to a CPLD and are
+1
drivers/leds/Makefile
··· 6 6 obj-$(CONFIG_LEDS_CLASS_FLASH) += led-class-flash.o 7 7 obj-$(CONFIG_LEDS_CLASS_MULTICOLOR) += led-class-multicolor.o 8 8 obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o 9 + obj-$(CONFIG_LEDS_KUNIT_TEST) += led-test.o 9 10 10 11 # LED Platform Drivers (keep this sorted, M-| sort) 11 12 obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o
+4 -2
drivers/leds/blink/leds-lgm-sso.c
··· 450 450 return !!(reg_val & BIT(offset)); 451 451 } 452 452 453 - static void sso_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 453 + static int sso_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 454 454 { 455 455 struct sso_led_priv *priv = gpiochip_get_data(chip); 456 456 ··· 458 458 if (!priv->gpio.freq) 459 459 regmap_update_bits(priv->mmap, SSO_CON0, SSO_CON0_SWU, 460 460 SSO_CON0_SWU); 461 + 462 + return 0; 461 463 } 462 464 463 465 static int sso_gpio_gc_init(struct device *dev, struct sso_led_priv *priv) ··· 471 469 gc->get_direction = sso_gpio_get_dir; 472 470 gc->direction_output = sso_gpio_dir_out; 473 471 gc->get = sso_gpio_get; 474 - gc->set = sso_gpio_set; 472 + gc->set_rv = sso_gpio_set; 475 473 476 474 gc->label = "lgm-sso"; 477 475 gc->base = -1;
+11
drivers/leds/flash/Kconfig
··· 132 132 133 133 This driver can be built as a module, it will be called "leds-sy7802". 134 134 135 + config LEDS_TPS6131X 136 + tristate "LED support for TI TPS6131x flash LED driver" 137 + depends on I2C && OF 138 + depends on GPIOLIB 139 + select REGMAP_I2C 140 + help 141 + This option enables support for Texas Instruments TPS61310/TPS61311 142 + flash LED driver. 143 + 144 + This driver can be built as a module, it will be called "leds-tps6131x". 145 + 135 146 endif # LEDS_CLASS_FLASH
+1
drivers/leds/flash/Makefile
··· 12 12 obj-$(CONFIG_LEDS_RT8515) += leds-rt8515.o 13 13 obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o 14 14 obj-$(CONFIG_LEDS_SY7802) += leds-sy7802.o 15 + obj-$(CONFIG_LEDS_TPS6131X) += leds-tps6131x.o
+815
drivers/leds/flash/leds-tps6131x.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Texas Instruments TPS61310/TPS61311 flash LED driver with I2C interface 4 + * 5 + * Copyright 2025 Matthias Fend <matthias.fend@emfend.at> 6 + */ 7 + 8 + #include <linux/gpio/consumer.h> 9 + #include <linux/i2c.h> 10 + #include <linux/led-class-flash.h> 11 + #include <linux/leds.h> 12 + #include <linux/module.h> 13 + #include <linux/regmap.h> 14 + #include <media/v4l2-flash-led-class.h> 15 + 16 + #define TPS6131X_REG_0 0x00 17 + #define TPS6131X_REG_0_RESET BIT(7) 18 + #define TPS6131X_REG_0_DCLC13 GENMASK(5, 3) 19 + #define TPS6131X_REG_0_DCLC13_SHIFT 3 20 + #define TPS6131X_REG_0_DCLC2 GENMASK(2, 0) 21 + #define TPS6131X_REG_0_DCLC2_SHIFT 0 22 + 23 + #define TPS6131X_REG_1 0x01 24 + #define TPS6131X_REG_1_MODE GENMASK(7, 6) 25 + #define TPS6131X_REG_1_MODE_SHIFT 6 26 + #define TPS6131X_REG_1_FC2 GENMASK(5, 0) 27 + #define TPS6131X_REG_1_FC2_SHIFT 0 28 + 29 + #define TPS6131X_REG_2 0x02 30 + #define TPS6131X_REG_2_MODE GENMASK(7, 6) 31 + #define TPS6131X_REG_2_MODE_SHIFT 6 32 + #define TPS6131X_REG_2_ENVM BIT(5) 33 + #define TPS6131X_REG_2_FC13 GENMASK(4, 0) 34 + #define TPS6131X_REG_2_FC13_SHIFT 0 35 + 36 + #define TPS6131X_REG_3 0x03 37 + #define TPS6131X_REG_3_STIM GENMASK(7, 5) 38 + #define TPS6131X_REG_3_STIM_SHIFT 5 39 + #define TPS6131X_REG_3_HPFL BIT(4) 40 + #define TPS6131X_REG_3_SELSTIM_TO BIT(3) 41 + #define TPS6131X_REG_3_STT BIT(2) 42 + #define TPS6131X_REG_3_SFT BIT(1) 43 + #define TPS6131X_REG_3_TXMASK BIT(0) 44 + 45 + #define TPS6131X_REG_4 0x04 46 + #define TPS6131X_REG_4_PG BIT(7) 47 + #define TPS6131X_REG_4_HOTDIE_HI BIT(6) 48 + #define TPS6131X_REG_4_HOTDIE_LO BIT(5) 49 + #define TPS6131X_REG_4_ILIM BIT(4) 50 + #define TPS6131X_REG_4_INDC GENMASK(3, 0) 51 + #define TPS6131X_REG_4_INDC_SHIFT 0 52 + 53 + #define TPS6131X_REG_5 0x05 54 + #define TPS6131X_REG_5_SELFCAL BIT(7) 55 + #define TPS6131X_REG_5_ENPSM BIT(6) 56 + #define TPS6131X_REG_5_STSTRB1_DIR BIT(5) 57 + #define TPS6131X_REG_5_GPIO BIT(4) 58 + #define TPS6131X_REG_5_GPIOTYPE BIT(3) 59 + #define TPS6131X_REG_5_ENLED3 BIT(2) 60 + #define TPS6131X_REG_5_ENLED2 BIT(1) 61 + #define TPS6131X_REG_5_ENLED1 BIT(0) 62 + 63 + #define TPS6131X_REG_6 0x06 64 + #define TPS6131X_REG_6_ENTS BIT(7) 65 + #define TPS6131X_REG_6_LEDHOT BIT(6) 66 + #define TPS6131X_REG_6_LEDWARN BIT(5) 67 + #define TPS6131X_REG_6_LEDHDR BIT(4) 68 + #define TPS6131X_REG_6_OV GENMASK(3, 0) 69 + #define TPS6131X_REG_6_OV_SHIFT 0 70 + 71 + #define TPS6131X_REG_7 0x07 72 + #define TPS6131X_REG_7_ENBATMON BIT(7) 73 + #define TPS6131X_REG_7_BATDROOP GENMASK(6, 4) 74 + #define TPS6131X_REG_7_BATDROOP_SHIFT 4 75 + #define TPS6131X_REG_7_REVID GENMASK(2, 0) 76 + #define TPS6131X_REG_7_REVID_SHIFT 0 77 + 78 + #define TPS6131X_MAX_CHANNELS 3 79 + 80 + #define TPS6131X_FLASH_MAX_I_CHAN13_MA 400 81 + #define TPS6131X_FLASH_MAX_I_CHAN2_MA 800 82 + #define TPS6131X_FLASH_STEP_I_MA 25 83 + 84 + #define TPS6131X_TORCH_MAX_I_CHAN13_MA 175 85 + #define TPS6131X_TORCH_MAX_I_CHAN2_MA 175 86 + #define TPS6131X_TORCH_STEP_I_MA 25 87 + 88 + /* The torch watchdog timer must be refreshed within an interval of 13 seconds. */ 89 + #define TPS6131X_TORCH_REFRESH_INTERVAL_JIFFIES msecs_to_jiffies(10000) 90 + 91 + #define UA_TO_MA(UA) ((UA) / 1000) 92 + 93 + enum tps6131x_mode { 94 + TPS6131X_MODE_SHUTDOWN = 0x0, 95 + TPS6131X_MODE_TORCH = 0x1, 96 + TPS6131X_MODE_FLASH = 0x2, 97 + }; 98 + 99 + struct tps6131x { 100 + struct device *dev; 101 + struct regmap *regmap; 102 + struct gpio_desc *reset_gpio; 103 + /* 104 + * Registers 0, 1, 2, and 3 control parts of the controller that are not completely 105 + * independent of each other. Since some operations require the registers to be written in 106 + * a specific order to avoid unwanted side effects, they are synchronized with a lock. 107 + */ 108 + struct mutex lock; /* Hardware access lock for register 0, 1, 2 and 3 */ 109 + struct delayed_work torch_refresh_work; 110 + bool valley_current_limit; 111 + bool chan1_en; 112 + bool chan2_en; 113 + bool chan3_en; 114 + struct fwnode_handle *led_node; 115 + u32 max_flash_current_ma; 116 + u32 step_flash_current_ma; 117 + u32 max_torch_current_ma; 118 + u32 step_torch_current_ma; 119 + u32 max_timeout_us; 120 + struct led_classdev_flash fled_cdev; 121 + struct v4l2_flash *v4l2_flash; 122 + }; 123 + 124 + static struct tps6131x *fled_cdev_to_tps6131x(struct led_classdev_flash *fled_cdev) 125 + { 126 + return container_of(fled_cdev, struct tps6131x, fled_cdev); 127 + } 128 + 129 + /* 130 + * Register contents after a power on/reset. These values cannot be changed. 131 + */ 132 + 133 + #define TPS6131X_DCLC2_50MA 2 134 + #define TPS6131X_DCLC13_25MA 1 135 + #define TPS6131X_FC2_400MA 16 136 + #define TPS6131X_FC13_200MA 8 137 + #define TPS6131X_STIM_0_579MS_1_37MS 6 138 + #define TPS6131X_SELSTIM_RANGE0 0 139 + #define TPS6131X_INDC_OFF 0 140 + #define TPS6131X_OV_4950MV 9 141 + #define TPS6131X_BATDROOP_150MV 4 142 + 143 + static const struct reg_default tps6131x_regmap_defaults[] = { 144 + { TPS6131X_REG_0, (TPS6131X_DCLC13_25MA << TPS6131X_REG_0_DCLC13_SHIFT) | 145 + (TPS6131X_DCLC2_50MA << TPS6131X_REG_0_DCLC2_SHIFT) }, 146 + { TPS6131X_REG_1, (TPS6131X_MODE_SHUTDOWN << TPS6131X_REG_1_MODE_SHIFT) | 147 + (TPS6131X_FC2_400MA << TPS6131X_REG_1_FC2_SHIFT) }, 148 + { TPS6131X_REG_2, (TPS6131X_MODE_SHUTDOWN << TPS6131X_REG_2_MODE_SHIFT) | 149 + (TPS6131X_FC13_200MA << TPS6131X_REG_2_FC13_SHIFT) }, 150 + { TPS6131X_REG_3, (TPS6131X_STIM_0_579MS_1_37MS << TPS6131X_REG_3_STIM_SHIFT) | 151 + (TPS6131X_SELSTIM_RANGE0 << TPS6131X_REG_3_SELSTIM_TO) | 152 + TPS6131X_REG_3_TXMASK }, 153 + { TPS6131X_REG_4, (TPS6131X_INDC_OFF << TPS6131X_REG_4_INDC_SHIFT) }, 154 + { TPS6131X_REG_5, TPS6131X_REG_5_ENPSM | TPS6131X_REG_5_STSTRB1_DIR | 155 + TPS6131X_REG_5_GPIOTYPE | TPS6131X_REG_5_ENLED2 }, 156 + { TPS6131X_REG_6, (TPS6131X_OV_4950MV << TPS6131X_REG_6_OV_SHIFT) }, 157 + { TPS6131X_REG_7, (TPS6131X_BATDROOP_150MV << TPS6131X_REG_7_BATDROOP_SHIFT) }, 158 + }; 159 + 160 + /* 161 + * These registers contain flags that are reset when read. 162 + */ 163 + static bool tps6131x_regmap_precious(struct device *dev, unsigned int reg) 164 + { 165 + switch (reg) { 166 + case TPS6131X_REG_3: 167 + case TPS6131X_REG_4: 168 + case TPS6131X_REG_6: 169 + return true; 170 + default: 171 + return false; 172 + } 173 + } 174 + 175 + static const struct regmap_config tps6131x_regmap = { 176 + .reg_bits = 8, 177 + .val_bits = 8, 178 + .max_register = TPS6131X_REG_7, 179 + .reg_defaults = tps6131x_regmap_defaults, 180 + .num_reg_defaults = ARRAY_SIZE(tps6131x_regmap_defaults), 181 + .cache_type = REGCACHE_FLAT, 182 + .precious_reg = &tps6131x_regmap_precious, 183 + }; 184 + 185 + struct tps6131x_timer_config { 186 + u8 val; 187 + u8 range; 188 + u32 time_us; 189 + }; 190 + 191 + static const struct tps6131x_timer_config tps6131x_timer_configs[] = { 192 + { .val = 0, .range = 1, .time_us = 5300 }, 193 + { .val = 1, .range = 1, .time_us = 10700 }, 194 + { .val = 2, .range = 1, .time_us = 16000 }, 195 + { .val = 3, .range = 1, .time_us = 21300 }, 196 + { .val = 4, .range = 1, .time_us = 26600 }, 197 + { .val = 5, .range = 1, .time_us = 32000 }, 198 + { .val = 6, .range = 1, .time_us = 37300 }, 199 + { .val = 0, .range = 0, .time_us = 68200 }, 200 + { .val = 7, .range = 1, .time_us = 71500 }, 201 + { .val = 1, .range = 0, .time_us = 102200 }, 202 + { .val = 2, .range = 0, .time_us = 136300 }, 203 + { .val = 3, .range = 0, .time_us = 170400 }, 204 + { .val = 4, .range = 0, .time_us = 204500 }, 205 + { .val = 5, .range = 0, .time_us = 340800 }, 206 + { .val = 6, .range = 0, .time_us = 579300 }, 207 + { .val = 7, .range = 0, .time_us = 852000 }, 208 + }; 209 + 210 + static const struct tps6131x_timer_config *tps6131x_find_closest_timer_config(u32 timeout_us) 211 + { 212 + const struct tps6131x_timer_config *timer_config = &tps6131x_timer_configs[0]; 213 + u32 diff, min_diff = U32_MAX; 214 + int i; 215 + 216 + for (i = 0; i < ARRAY_SIZE(tps6131x_timer_configs); i++) { 217 + diff = abs(tps6131x_timer_configs[i].time_us - timeout_us); 218 + if (diff < min_diff) { 219 + timer_config = &tps6131x_timer_configs[i]; 220 + min_diff = diff; 221 + if (!min_diff) 222 + break; 223 + } 224 + } 225 + 226 + return timer_config; 227 + } 228 + 229 + static int tps6131x_reset_chip(struct tps6131x *tps6131x) 230 + { 231 + int ret; 232 + 233 + if (tps6131x->reset_gpio) { 234 + gpiod_set_value_cansleep(tps6131x->reset_gpio, 1); 235 + fsleep(10); 236 + gpiod_set_value_cansleep(tps6131x->reset_gpio, 0); 237 + fsleep(100); 238 + } else { 239 + ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_0, TPS6131X_REG_0_RESET, 240 + TPS6131X_REG_0_RESET); 241 + if (ret) 242 + return ret; 243 + 244 + fsleep(100); 245 + 246 + ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_0, TPS6131X_REG_0_RESET, 0); 247 + if (ret) 248 + return ret; 249 + } 250 + 251 + return 0; 252 + } 253 + 254 + static int tps6131x_init_chip(struct tps6131x *tps6131x) 255 + { 256 + u32 val; 257 + int ret; 258 + 259 + val = tps6131x->valley_current_limit ? TPS6131X_REG_4_ILIM : 0; 260 + 261 + ret = regmap_write(tps6131x->regmap, TPS6131X_REG_4, val); 262 + if (ret) 263 + return ret; 264 + 265 + val = TPS6131X_REG_5_ENPSM | TPS6131X_REG_5_STSTRB1_DIR | TPS6131X_REG_5_GPIOTYPE; 266 + 267 + if (tps6131x->chan1_en) 268 + val |= TPS6131X_REG_5_ENLED1; 269 + 270 + if (tps6131x->chan2_en) 271 + val |= TPS6131X_REG_5_ENLED2; 272 + 273 + if (tps6131x->chan3_en) 274 + val |= TPS6131X_REG_5_ENLED3; 275 + 276 + ret = regmap_write(tps6131x->regmap, TPS6131X_REG_5, val); 277 + if (ret) 278 + return ret; 279 + 280 + val = TPS6131X_REG_6_ENTS; 281 + 282 + ret = regmap_write(tps6131x->regmap, TPS6131X_REG_6, val); 283 + if (ret) 284 + return ret; 285 + 286 + return 0; 287 + } 288 + 289 + static int tps6131x_set_mode(struct tps6131x *tps6131x, enum tps6131x_mode mode, bool force) 290 + { 291 + u8 val = mode << TPS6131X_REG_1_MODE_SHIFT; 292 + 293 + return regmap_update_bits_base(tps6131x->regmap, TPS6131X_REG_1, TPS6131X_REG_1_MODE, val, 294 + NULL, false, force); 295 + } 296 + 297 + static void tps6131x_torch_refresh_handler(struct work_struct *work) 298 + { 299 + struct tps6131x *tps6131x = container_of(work, struct tps6131x, torch_refresh_work.work); 300 + int ret; 301 + 302 + guard(mutex)(&tps6131x->lock); 303 + 304 + ret = tps6131x_set_mode(tps6131x, TPS6131X_MODE_TORCH, true); 305 + if (ret < 0) { 306 + dev_err(tps6131x->dev, "Failed to refresh torch watchdog timer\n"); 307 + return; 308 + } 309 + 310 + schedule_delayed_work(&tps6131x->torch_refresh_work, 311 + TPS6131X_TORCH_REFRESH_INTERVAL_JIFFIES); 312 + } 313 + 314 + static int tps6131x_brightness_set(struct led_classdev *cdev, enum led_brightness brightness) 315 + { 316 + struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(cdev); 317 + struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 318 + u32 num_chans, steps_chan13, steps_chan2, steps_remaining; 319 + u8 reg0; 320 + int ret; 321 + 322 + cancel_delayed_work_sync(&tps6131x->torch_refresh_work); 323 + 324 + /* 325 + * The brightness parameter uses the number of current steps as the unit (not the current 326 + * value itself). Since the reported step size can vary depending on the configuration, 327 + * this value must be converted into actual register steps. 328 + */ 329 + steps_remaining = (brightness * tps6131x->step_torch_current_ma) / TPS6131X_TORCH_STEP_I_MA; 330 + 331 + num_chans = tps6131x->chan1_en + tps6131x->chan2_en + tps6131x->chan3_en; 332 + 333 + /* 334 + * The currents are distributed as evenly as possible across the activated channels. 335 + * Since channels 1 and 3 share the same register setting, they always use the same current 336 + * value. Channel 2 supports higher currents and thus takes over the remaining additional 337 + * portion that cannot be covered by the other channels. 338 + */ 339 + steps_chan13 = min_t(u32, steps_remaining / num_chans, 340 + TPS6131X_TORCH_MAX_I_CHAN13_MA / TPS6131X_TORCH_STEP_I_MA); 341 + if (tps6131x->chan1_en) 342 + steps_remaining -= steps_chan13; 343 + if (tps6131x->chan3_en) 344 + steps_remaining -= steps_chan13; 345 + 346 + steps_chan2 = min_t(u32, steps_remaining, 347 + TPS6131X_TORCH_MAX_I_CHAN2_MA / TPS6131X_TORCH_STEP_I_MA); 348 + 349 + guard(mutex)(&tps6131x->lock); 350 + 351 + reg0 = (steps_chan13 << TPS6131X_REG_0_DCLC13_SHIFT) | 352 + (steps_chan2 << TPS6131X_REG_0_DCLC2_SHIFT); 353 + ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_0, 354 + TPS6131X_REG_0_DCLC13 | TPS6131X_REG_0_DCLC2, reg0); 355 + if (ret < 0) 356 + return ret; 357 + 358 + ret = tps6131x_set_mode(tps6131x, brightness ? TPS6131X_MODE_TORCH : TPS6131X_MODE_SHUTDOWN, 359 + true); 360 + if (ret < 0) 361 + return ret; 362 + 363 + /* 364 + * In order to use both the flash and the video light functions purely via the I2C 365 + * interface, STRB1 must be low. If STRB1 is low, then the video light watchdog timer 366 + * is also active, which puts the device into the shutdown state after around 13 seconds. 367 + * To prevent this, the mode must be refreshed within the watchdog timeout. 368 + */ 369 + if (brightness) 370 + schedule_delayed_work(&tps6131x->torch_refresh_work, 371 + TPS6131X_TORCH_REFRESH_INTERVAL_JIFFIES); 372 + 373 + return 0; 374 + } 375 + 376 + static int tps6131x_strobe_set(struct led_classdev_flash *fled_cdev, bool state) 377 + { 378 + struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 379 + int ret; 380 + 381 + guard(mutex)(&tps6131x->lock); 382 + 383 + ret = tps6131x_set_mode(tps6131x, state ? TPS6131X_MODE_FLASH : TPS6131X_MODE_SHUTDOWN, 384 + true); 385 + if (ret < 0) 386 + return ret; 387 + 388 + if (state) { 389 + ret = regmap_update_bits_base(tps6131x->regmap, TPS6131X_REG_3, TPS6131X_REG_3_SFT, 390 + TPS6131X_REG_3_SFT, NULL, false, true); 391 + if (ret) 392 + return ret; 393 + } 394 + 395 + ret = regmap_update_bits_base(tps6131x->regmap, TPS6131X_REG_3, TPS6131X_REG_3_SFT, 0, NULL, 396 + false, true); 397 + if (ret) 398 + return ret; 399 + 400 + return 0; 401 + } 402 + 403 + static int tps6131x_flash_brightness_set(struct led_classdev_flash *fled_cdev, u32 brightness) 404 + { 405 + struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 406 + u32 num_chans; 407 + u32 steps_chan13, steps_chan2; 408 + u32 steps_remaining; 409 + int ret; 410 + 411 + steps_remaining = brightness / TPS6131X_FLASH_STEP_I_MA; 412 + num_chans = tps6131x->chan1_en + tps6131x->chan2_en + tps6131x->chan3_en; 413 + steps_chan13 = min_t(u32, steps_remaining / num_chans, 414 + TPS6131X_FLASH_MAX_I_CHAN13_MA / TPS6131X_FLASH_STEP_I_MA); 415 + if (tps6131x->chan1_en) 416 + steps_remaining -= steps_chan13; 417 + if (tps6131x->chan3_en) 418 + steps_remaining -= steps_chan13; 419 + steps_chan2 = min_t(u32, steps_remaining, 420 + TPS6131X_FLASH_MAX_I_CHAN2_MA / TPS6131X_FLASH_STEP_I_MA); 421 + 422 + guard(mutex)(&tps6131x->lock); 423 + 424 + ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_2, TPS6131X_REG_2_FC13, 425 + steps_chan13 << TPS6131X_REG_2_FC13_SHIFT); 426 + if (ret < 0) 427 + return ret; 428 + 429 + ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_1, TPS6131X_REG_1_FC2, 430 + steps_chan2 << TPS6131X_REG_1_FC2_SHIFT); 431 + if (ret < 0) 432 + return ret; 433 + 434 + fled_cdev->brightness.val = brightness; 435 + 436 + return 0; 437 + } 438 + 439 + static int tps6131x_flash_timeout_set(struct led_classdev_flash *fled_cdev, u32 timeout_us) 440 + { 441 + const struct tps6131x_timer_config *timer_config; 442 + struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 443 + u8 reg3; 444 + int ret; 445 + 446 + guard(mutex)(&tps6131x->lock); 447 + 448 + timer_config = tps6131x_find_closest_timer_config(timeout_us); 449 + 450 + reg3 = timer_config->val << TPS6131X_REG_3_STIM_SHIFT; 451 + if (timer_config->range) 452 + reg3 |= TPS6131X_REG_3_SELSTIM_TO; 453 + 454 + ret = regmap_update_bits(tps6131x->regmap, TPS6131X_REG_3, 455 + TPS6131X_REG_3_STIM | TPS6131X_REG_3_SELSTIM_TO, reg3); 456 + if (ret < 0) 457 + return ret; 458 + 459 + fled_cdev->timeout.val = timer_config->time_us; 460 + 461 + return 0; 462 + } 463 + 464 + static int tps6131x_strobe_get(struct led_classdev_flash *fled_cdev, bool *state) 465 + { 466 + struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 467 + unsigned int reg3; 468 + int ret; 469 + 470 + ret = regmap_read_bypassed(tps6131x->regmap, TPS6131X_REG_3, &reg3); 471 + if (ret) 472 + return ret; 473 + 474 + *state = !!(reg3 & TPS6131X_REG_3_SFT); 475 + 476 + return 0; 477 + } 478 + 479 + static int tps6131x_flash_fault_get(struct led_classdev_flash *fled_cdev, u32 *fault) 480 + { 481 + struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 482 + unsigned int reg3, reg4, reg6; 483 + int ret; 484 + 485 + *fault = 0; 486 + 487 + ret = regmap_read_bypassed(tps6131x->regmap, TPS6131X_REG_3, &reg3); 488 + if (ret < 0) 489 + return ret; 490 + 491 + ret = regmap_read_bypassed(tps6131x->regmap, TPS6131X_REG_4, &reg4); 492 + if (ret < 0) 493 + return ret; 494 + 495 + ret = regmap_read_bypassed(tps6131x->regmap, TPS6131X_REG_6, &reg6); 496 + if (ret < 0) 497 + return ret; 498 + 499 + if (reg3 & TPS6131X_REG_3_HPFL) 500 + *fault |= LED_FAULT_SHORT_CIRCUIT; 501 + 502 + if (reg3 & TPS6131X_REG_3_SELSTIM_TO) 503 + *fault |= LED_FAULT_TIMEOUT; 504 + 505 + if (reg4 & TPS6131X_REG_4_HOTDIE_HI) 506 + *fault |= LED_FAULT_OVER_TEMPERATURE; 507 + 508 + if (reg6 & (TPS6131X_REG_6_LEDHOT | TPS6131X_REG_6_LEDWARN)) 509 + *fault |= LED_FAULT_LED_OVER_TEMPERATURE; 510 + 511 + if (!(reg6 & TPS6131X_REG_6_LEDHDR)) 512 + *fault |= LED_FAULT_UNDER_VOLTAGE; 513 + 514 + if (reg6 & TPS6131X_REG_6_LEDHOT) { 515 + ret = regmap_update_bits_base(tps6131x->regmap, TPS6131X_REG_6, 516 + TPS6131X_REG_6_LEDHOT, 0, NULL, false, true); 517 + if (ret < 0) 518 + return ret; 519 + } 520 + 521 + return 0; 522 + } 523 + 524 + static const struct led_flash_ops flash_ops = { 525 + .flash_brightness_set = tps6131x_flash_brightness_set, 526 + .strobe_set = tps6131x_strobe_set, 527 + .strobe_get = tps6131x_strobe_get, 528 + .timeout_set = tps6131x_flash_timeout_set, 529 + .fault_get = tps6131x_flash_fault_get, 530 + }; 531 + 532 + static int tps6131x_parse_node(struct tps6131x *tps6131x) 533 + { 534 + const struct tps6131x_timer_config *timer_config; 535 + struct device *dev = tps6131x->dev; 536 + u32 channels[TPS6131X_MAX_CHANNELS]; 537 + u32 current_step_multiplier; 538 + u32 current_ua; 539 + u32 max_current_flash_ma, max_current_torch_ma; 540 + u32 timeout_us; 541 + int num_channels; 542 + int i; 543 + int ret; 544 + 545 + tps6131x->valley_current_limit = device_property_read_bool(dev, "ti,valley-current-limit"); 546 + 547 + tps6131x->led_node = fwnode_get_next_available_child_node(dev->fwnode, NULL); 548 + if (!tps6131x->led_node) { 549 + dev_err(dev, "Missing LED node\n"); 550 + return -EINVAL; 551 + } 552 + 553 + num_channels = fwnode_property_count_u32(tps6131x->led_node, "led-sources"); 554 + if (num_channels <= 0) { 555 + dev_err(dev, "Failed to read led-sources property\n"); 556 + return -EINVAL; 557 + } 558 + 559 + if (num_channels > TPS6131X_MAX_CHANNELS) { 560 + dev_err(dev, "led-sources count %u exceeds maximum channel count %u\n", 561 + num_channels, TPS6131X_MAX_CHANNELS); 562 + return -EINVAL; 563 + } 564 + 565 + ret = fwnode_property_read_u32_array(tps6131x->led_node, "led-sources", channels, 566 + num_channels); 567 + if (ret < 0) { 568 + dev_err(dev, "Failed to read led-sources property\n"); 569 + return ret; 570 + } 571 + 572 + max_current_flash_ma = 0; 573 + max_current_torch_ma = 0; 574 + for (i = 0; i < num_channels; i++) { 575 + switch (channels[i]) { 576 + case 1: 577 + tps6131x->chan1_en = true; 578 + max_current_flash_ma += TPS6131X_FLASH_MAX_I_CHAN13_MA; 579 + max_current_torch_ma += TPS6131X_TORCH_MAX_I_CHAN13_MA; 580 + break; 581 + case 2: 582 + tps6131x->chan2_en = true; 583 + max_current_flash_ma += TPS6131X_FLASH_MAX_I_CHAN2_MA; 584 + max_current_torch_ma += TPS6131X_TORCH_MAX_I_CHAN2_MA; 585 + break; 586 + case 3: 587 + tps6131x->chan3_en = true; 588 + max_current_flash_ma += TPS6131X_FLASH_MAX_I_CHAN13_MA; 589 + max_current_torch_ma += TPS6131X_TORCH_MAX_I_CHAN13_MA; 590 + break; 591 + default: 592 + dev_err(dev, "led-source out of range [1-3]\n"); 593 + return -EINVAL; 594 + } 595 + } 596 + 597 + /* 598 + * If only channels 1 and 3 are used, the step size is doubled because the two channels 599 + * share the same current control register. 600 + */ 601 + current_step_multiplier = 602 + (tps6131x->chan1_en && tps6131x->chan3_en && !tps6131x->chan2_en) ? 2 : 1; 603 + tps6131x->step_flash_current_ma = current_step_multiplier * TPS6131X_FLASH_STEP_I_MA; 604 + tps6131x->step_torch_current_ma = current_step_multiplier * TPS6131X_TORCH_STEP_I_MA; 605 + 606 + ret = fwnode_property_read_u32(tps6131x->led_node, "led-max-microamp", &current_ua); 607 + if (ret < 0) { 608 + dev_err(dev, "Failed to read led-max-microamp property\n"); 609 + return ret; 610 + } 611 + 612 + tps6131x->max_torch_current_ma = UA_TO_MA(current_ua); 613 + 614 + if (!tps6131x->max_torch_current_ma || 615 + tps6131x->max_torch_current_ma > max_current_torch_ma || 616 + (tps6131x->max_torch_current_ma % tps6131x->step_torch_current_ma)) { 617 + dev_err(dev, "led-max-microamp out of range or not a multiple of %u\n", 618 + tps6131x->step_torch_current_ma); 619 + return -EINVAL; 620 + } 621 + 622 + ret = fwnode_property_read_u32(tps6131x->led_node, "flash-max-microamp", &current_ua); 623 + if (ret < 0) { 624 + dev_err(dev, "Failed to read flash-max-microamp property\n"); 625 + return ret; 626 + } 627 + 628 + tps6131x->max_flash_current_ma = UA_TO_MA(current_ua); 629 + 630 + if (!tps6131x->max_flash_current_ma || 631 + tps6131x->max_flash_current_ma > max_current_flash_ma || 632 + (tps6131x->max_flash_current_ma % tps6131x->step_flash_current_ma)) { 633 + dev_err(dev, "flash-max-microamp out of range or not a multiple of %u\n", 634 + tps6131x->step_flash_current_ma); 635 + return -EINVAL; 636 + } 637 + 638 + ret = fwnode_property_read_u32(tps6131x->led_node, "flash-max-timeout-us", &timeout_us); 639 + if (ret < 0) { 640 + dev_err(dev, "Failed to read flash-max-timeout-us property\n"); 641 + return ret; 642 + } 643 + 644 + timer_config = tps6131x_find_closest_timer_config(timeout_us); 645 + tps6131x->max_timeout_us = timer_config->time_us; 646 + 647 + if (tps6131x->max_timeout_us != timeout_us) 648 + dev_warn(dev, "flash-max-timeout-us %u not supported (using %u)\n", timeout_us, 649 + tps6131x->max_timeout_us); 650 + 651 + return 0; 652 + } 653 + 654 + static int tps6131x_led_class_setup(struct tps6131x *tps6131x) 655 + { 656 + const struct tps6131x_timer_config *timer_config; 657 + struct led_classdev *led_cdev; 658 + struct led_flash_setting *setting; 659 + struct led_init_data init_data = {}; 660 + int ret; 661 + 662 + tps6131x->fled_cdev.ops = &flash_ops; 663 + 664 + setting = &tps6131x->fled_cdev.timeout; 665 + timer_config = tps6131x_find_closest_timer_config(0); 666 + setting->min = timer_config->time_us; 667 + setting->max = tps6131x->max_timeout_us; 668 + setting->step = 1; /* Only some specific time periods are supported. No fixed step size. */ 669 + setting->val = setting->min; 670 + 671 + setting = &tps6131x->fled_cdev.brightness; 672 + setting->min = tps6131x->step_flash_current_ma; 673 + setting->max = tps6131x->max_flash_current_ma; 674 + setting->step = tps6131x->step_flash_current_ma; 675 + setting->val = setting->min; 676 + 677 + led_cdev = &tps6131x->fled_cdev.led_cdev; 678 + led_cdev->brightness_set_blocking = tps6131x_brightness_set; 679 + led_cdev->max_brightness = tps6131x->max_torch_current_ma; 680 + led_cdev->flags |= LED_DEV_CAP_FLASH; 681 + 682 + init_data.fwnode = tps6131x->led_node; 683 + init_data.devicename = NULL; 684 + init_data.default_label = NULL; 685 + init_data.devname_mandatory = false; 686 + 687 + ret = devm_led_classdev_flash_register_ext(tps6131x->dev, &tps6131x->fled_cdev, 688 + &init_data); 689 + if (ret) 690 + return ret; 691 + 692 + return 0; 693 + } 694 + 695 + static int tps6131x_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, bool enable) 696 + { 697 + struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev; 698 + struct tps6131x *tps6131x = fled_cdev_to_tps6131x(fled_cdev); 699 + 700 + guard(mutex)(&tps6131x->lock); 701 + 702 + return tps6131x_set_mode(tps6131x, enable ? TPS6131X_MODE_FLASH : TPS6131X_MODE_SHUTDOWN, 703 + false); 704 + } 705 + 706 + static const struct v4l2_flash_ops tps6131x_v4l2_flash_ops = { 707 + .external_strobe_set = tps6131x_flash_external_strobe_set, 708 + }; 709 + 710 + static int tps6131x_v4l2_setup(struct tps6131x *tps6131x) 711 + { 712 + struct v4l2_flash_config v4l2_cfg = { 0 }; 713 + struct led_flash_setting *intensity = &v4l2_cfg.intensity; 714 + 715 + intensity->min = tps6131x->step_torch_current_ma; 716 + intensity->max = tps6131x->max_torch_current_ma; 717 + intensity->step = tps6131x->step_torch_current_ma; 718 + intensity->val = intensity->min; 719 + 720 + strscpy(v4l2_cfg.dev_name, tps6131x->fled_cdev.led_cdev.dev->kobj.name, 721 + sizeof(v4l2_cfg.dev_name)); 722 + 723 + v4l2_cfg.has_external_strobe = true; 724 + v4l2_cfg.flash_faults = LED_FAULT_TIMEOUT | LED_FAULT_OVER_TEMPERATURE | 725 + LED_FAULT_SHORT_CIRCUIT | LED_FAULT_UNDER_VOLTAGE | 726 + LED_FAULT_LED_OVER_TEMPERATURE; 727 + 728 + tps6131x->v4l2_flash = v4l2_flash_init(tps6131x->dev, tps6131x->led_node, 729 + &tps6131x->fled_cdev, &tps6131x_v4l2_flash_ops, 730 + &v4l2_cfg); 731 + if (IS_ERR(tps6131x->v4l2_flash)) { 732 + dev_err(tps6131x->dev, "Failed to initialize v4l2 flash LED\n"); 733 + return PTR_ERR(tps6131x->v4l2_flash); 734 + } 735 + 736 + return 0; 737 + } 738 + 739 + static int tps6131x_probe(struct i2c_client *client) 740 + { 741 + struct tps6131x *tps6131x; 742 + int ret; 743 + 744 + tps6131x = devm_kzalloc(&client->dev, sizeof(*tps6131x), GFP_KERNEL); 745 + if (!tps6131x) 746 + return -ENOMEM; 747 + 748 + tps6131x->dev = &client->dev; 749 + i2c_set_clientdata(client, tps6131x); 750 + mutex_init(&tps6131x->lock); 751 + INIT_DELAYED_WORK(&tps6131x->torch_refresh_work, tps6131x_torch_refresh_handler); 752 + 753 + ret = tps6131x_parse_node(tps6131x); 754 + if (ret) 755 + return ret; 756 + 757 + tps6131x->regmap = devm_regmap_init_i2c(client, &tps6131x_regmap); 758 + if (IS_ERR(tps6131x->regmap)) { 759 + ret = PTR_ERR(tps6131x->regmap); 760 + return dev_err_probe(&client->dev, ret, "Failed to allocate register map\n"); 761 + } 762 + 763 + tps6131x->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); 764 + if (IS_ERR(tps6131x->reset_gpio)) { 765 + ret = PTR_ERR(tps6131x->reset_gpio); 766 + return dev_err_probe(&client->dev, ret, "Failed to get reset GPIO\n"); 767 + } 768 + 769 + ret = tps6131x_reset_chip(tps6131x); 770 + if (ret) 771 + return dev_err_probe(&client->dev, ret, "Failed to reset LED controller\n"); 772 + 773 + ret = tps6131x_init_chip(tps6131x); 774 + if (ret) 775 + return dev_err_probe(&client->dev, ret, "Failed to initialize LED controller\n"); 776 + 777 + ret = tps6131x_led_class_setup(tps6131x); 778 + if (ret) 779 + return dev_err_probe(&client->dev, ret, "Failed to setup LED class\n"); 780 + 781 + ret = tps6131x_v4l2_setup(tps6131x); 782 + if (ret) 783 + return dev_err_probe(&client->dev, ret, "Failed to setup v4l2 flash\n"); 784 + 785 + return 0; 786 + } 787 + 788 + static void tps6131x_remove(struct i2c_client *client) 789 + { 790 + struct tps6131x *tps6131x = i2c_get_clientdata(client); 791 + 792 + v4l2_flash_release(tps6131x->v4l2_flash); 793 + 794 + cancel_delayed_work_sync(&tps6131x->torch_refresh_work); 795 + } 796 + 797 + static const struct of_device_id of_tps6131x_leds_match[] = { 798 + { .compatible = "ti,tps61310" }, 799 + {} 800 + }; 801 + MODULE_DEVICE_TABLE(of, of_tps6131x_leds_match); 802 + 803 + static struct i2c_driver tps6131x_i2c_driver = { 804 + .driver = { 805 + .name = "tps6131x", 806 + .of_match_table = of_tps6131x_leds_match, 807 + }, 808 + .probe = tps6131x_probe, 809 + .remove = tps6131x_remove, 810 + }; 811 + module_i2c_driver(tps6131x_i2c_driver); 812 + 813 + MODULE_DESCRIPTION("Texas Instruments TPS6131X flash LED driver"); 814 + MODULE_AUTHOR("Matthias Fend <matthias.fend@emfend.at>"); 815 + MODULE_LICENSE("GPL");
+15
drivers/leds/led-class-flash.c
··· 440 440 } 441 441 EXPORT_SYMBOL_GPL(led_update_flash_brightness); 442 442 443 + int led_set_flash_duration(struct led_classdev_flash *fled_cdev, u32 duration) 444 + { 445 + struct led_classdev *led_cdev = &fled_cdev->led_cdev; 446 + struct led_flash_setting *s = &fled_cdev->duration; 447 + 448 + s->val = duration; 449 + led_clamp_align(s); 450 + 451 + if (!(led_cdev->flags & LED_SUSPENDED)) 452 + return call_flash_op(fled_cdev, duration_set, s->val); 453 + 454 + return 0; 455 + } 456 + EXPORT_SYMBOL_GPL(led_set_flash_duration); 457 + 443 458 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>"); 444 459 MODULE_DESCRIPTION("LED Flash class interface"); 445 460 MODULE_LICENSE("GPL v2");
+2 -1
drivers/leds/led-class-multicolor.c
··· 59 59 for (i = 0; i < mcled_cdev->num_colors; i++) 60 60 mcled_cdev->subled_info[i].intensity = intensity_value[i]; 61 61 62 - led_set_brightness(led_cdev, led_cdev->brightness); 62 + if (!test_bit(LED_BLINK_SW, &led_cdev->work_flags)) 63 + led_set_brightness(led_cdev, led_cdev->brightness); 63 64 ret = size; 64 65 err_out: 65 66 mutex_unlock(&led_cdev->led_access);
+25 -20
drivers/leds/led-core.c
··· 529 529 struct led_properties props = {}; 530 530 struct fwnode_handle *fwnode = init_data->fwnode; 531 531 const char *devicename = init_data->devicename; 532 + int n; 532 533 533 534 if (!led_classdev_name) 534 535 return -EINVAL; ··· 543 542 * Otherwise the label is prepended with devicename to compose 544 543 * the final LED class device name. 545 544 */ 546 - if (!devicename) { 547 - strscpy(led_classdev_name, props.label, 548 - LED_MAX_NAME_SIZE); 545 + if (devicename) { 546 + n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", 547 + devicename, props.label); 549 548 } else { 550 - snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", 551 - devicename, props.label); 549 + n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s", props.label); 552 550 } 553 551 } else if (props.function || props.color_present) { 554 552 char tmp_buf[LED_MAX_NAME_SIZE]; 555 553 556 554 if (props.func_enum_present) { 557 - snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s-%d", 558 - props.color_present ? led_colors[props.color] : "", 559 - props.function ?: "", props.func_enum); 555 + n = snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s-%d", 556 + props.color_present ? led_colors[props.color] : "", 557 + props.function ?: "", props.func_enum); 560 558 } else { 561 - snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s", 562 - props.color_present ? led_colors[props.color] : "", 563 - props.function ?: ""); 559 + n = snprintf(tmp_buf, LED_MAX_NAME_SIZE, "%s:%s", 560 + props.color_present ? led_colors[props.color] : "", 561 + props.function ?: ""); 564 562 } 565 - if (init_data->devname_mandatory) { 566 - snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", 567 - devicename, tmp_buf); 568 - } else { 569 - strscpy(led_classdev_name, tmp_buf, LED_MAX_NAME_SIZE); 563 + if (n >= LED_MAX_NAME_SIZE) 564 + return -E2BIG; 570 565 566 + if (init_data->devname_mandatory) { 567 + n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", 568 + devicename, tmp_buf); 569 + } else { 570 + n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s", tmp_buf); 571 571 } 572 572 } else if (init_data->default_label) { 573 573 if (!devicename) { 574 574 dev_err(dev, "Legacy LED naming requires devicename segment"); 575 575 return -EINVAL; 576 576 } 577 - snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", 578 - devicename, init_data->default_label); 577 + n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s:%s", 578 + devicename, init_data->default_label); 579 579 } else if (is_of_node(fwnode)) { 580 - strscpy(led_classdev_name, to_of_node(fwnode)->name, 581 - LED_MAX_NAME_SIZE); 580 + n = snprintf(led_classdev_name, LED_MAX_NAME_SIZE, "%s", 581 + to_of_node(fwnode)->name); 582 582 } else 583 583 return -EINVAL; 584 + 585 + if (n >= LED_MAX_NAME_SIZE) 586 + return -E2BIG; 584 587 585 588 return 0; 586 589 }
+132
drivers/leds/led-test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2025 Google LLC 4 + * 5 + * Author: Lee Jones <lee@kernel.org> 6 + */ 7 + 8 + #include <kunit/device.h> 9 + #include <kunit/test.h> 10 + #include <linux/device.h> 11 + #include <linux/leds.h> 12 + 13 + #define LED_TEST_POST_REG_BRIGHTNESS 10 14 + 15 + struct led_test_ddata { 16 + struct led_classdev cdev; 17 + struct device *dev; 18 + }; 19 + 20 + static enum led_brightness led_test_brightness_get(struct led_classdev *cdev) 21 + { 22 + return LED_TEST_POST_REG_BRIGHTNESS; 23 + } 24 + 25 + static void led_test_class_register(struct kunit *test) 26 + { 27 + struct led_test_ddata *ddata = test->priv; 28 + struct led_classdev *cdev_clash, *cdev = &ddata->cdev; 29 + struct device *dev = ddata->dev; 30 + int ret; 31 + 32 + /* Register a LED class device */ 33 + cdev->name = "led-test"; 34 + cdev->brightness_get = led_test_brightness_get; 35 + cdev->brightness = 0; 36 + 37 + ret = devm_led_classdev_register(dev, cdev); 38 + KUNIT_ASSERT_EQ(test, ret, 0); 39 + 40 + KUNIT_EXPECT_EQ(test, cdev->max_brightness, LED_FULL); 41 + KUNIT_EXPECT_EQ(test, cdev->brightness, LED_TEST_POST_REG_BRIGHTNESS); 42 + KUNIT_EXPECT_STREQ(test, cdev->dev->kobj.name, "led-test"); 43 + 44 + /* Register again with the same name - expect it to pass with the LED renamed */ 45 + cdev_clash = devm_kmemdup(dev, cdev, sizeof(*cdev), GFP_KERNEL); 46 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cdev_clash); 47 + 48 + ret = devm_led_classdev_register(dev, cdev_clash); 49 + KUNIT_ASSERT_EQ(test, ret, 0); 50 + 51 + KUNIT_EXPECT_STREQ(test, cdev_clash->dev->kobj.name, "led-test_1"); 52 + KUNIT_EXPECT_STREQ(test, cdev_clash->name, "led-test"); 53 + 54 + /* Enable name conflict rejection and register with the same name again - expect failure */ 55 + cdev_clash->flags |= LED_REJECT_NAME_CONFLICT; 56 + ret = devm_led_classdev_register(dev, cdev_clash); 57 + KUNIT_EXPECT_EQ(test, ret, -EEXIST); 58 + } 59 + 60 + static void led_test_class_add_lookup_and_get(struct kunit *test) 61 + { 62 + struct led_test_ddata *ddata = test->priv; 63 + struct led_classdev *cdev = &ddata->cdev, *cdev_get; 64 + struct device *dev = ddata->dev; 65 + struct led_lookup_data lookup; 66 + int ret; 67 + 68 + /* First, register a LED class device */ 69 + cdev->name = "led-test"; 70 + ret = devm_led_classdev_register(dev, cdev); 71 + KUNIT_ASSERT_EQ(test, ret, 0); 72 + 73 + /* Then make the LED available for lookup */ 74 + lookup.provider = cdev->name; 75 + lookup.dev_id = dev_name(dev); 76 + lookup.con_id = "led-test-1"; 77 + led_add_lookup(&lookup); 78 + 79 + /* Finally, attempt to look it up via the API - imagine this was an orthogonal driver */ 80 + cdev_get = devm_led_get(dev, "led-test-1"); 81 + KUNIT_ASSERT_FALSE(test, IS_ERR(cdev_get)); 82 + 83 + KUNIT_EXPECT_STREQ(test, cdev_get->name, cdev->name); 84 + 85 + led_remove_lookup(&lookup); 86 + } 87 + 88 + static struct kunit_case led_test_cases[] = { 89 + KUNIT_CASE(led_test_class_register), 90 + KUNIT_CASE(led_test_class_add_lookup_and_get), 91 + { } 92 + }; 93 + 94 + static int led_test_init(struct kunit *test) 95 + { 96 + struct led_test_ddata *ddata; 97 + struct device *dev; 98 + 99 + ddata = kunit_kzalloc(test, sizeof(*ddata), GFP_KERNEL); 100 + if (!ddata) 101 + return -ENOMEM; 102 + 103 + test->priv = ddata; 104 + 105 + dev = kunit_device_register(test, "led_test"); 106 + if (IS_ERR(dev)) 107 + return PTR_ERR(dev); 108 + 109 + ddata->dev = get_device(dev); 110 + 111 + return 0; 112 + } 113 + 114 + static void led_test_exit(struct kunit *test) 115 + { 116 + struct led_test_ddata *ddata = test->priv; 117 + 118 + if (ddata && ddata->dev) 119 + put_device(ddata->dev); 120 + } 121 + 122 + static struct kunit_suite led_test_suite = { 123 + .name = "led", 124 + .init = led_test_init, 125 + .exit = led_test_exit, 126 + .test_cases = led_test_cases, 127 + }; 128 + kunit_test_suite(led_test_suite); 129 + 130 + MODULE_AUTHOR("Lee Jones <lee@kernel.org>"); 131 + MODULE_DESCRIPTION("KUnit tests for the LED framework"); 132 + MODULE_LICENSE("GPL");
+13
drivers/leds/led-triggers.c
··· 54 54 goto unlock; 55 55 } 56 56 57 + if (sysfs_streq(buf, "default")) { 58 + led_trigger_set_default(led_cdev); 59 + goto unlock; 60 + } 61 + 57 62 down_read(&triggers_list_lock); 58 63 list_for_each_entry(trig, &trigger_list, next_trig) { 59 64 if (sysfs_streq(buf, trig->name) && trigger_relevant(led_cdev, trig)) { ··· 102 97 struct led_trigger *trig; 103 98 int len = led_trigger_snprintf(buf, size, "%s", 104 99 led_cdev->trigger ? "none" : "[none]"); 100 + 101 + if (led_cdev->default_trigger) 102 + len += led_trigger_snprintf(buf + len, size - len, " default"); 105 103 106 104 list_for_each_entry(trig, &trigger_list, next_trig) { 107 105 bool hit; ··· 288 280 289 281 if (!led_cdev->default_trigger) 290 282 return; 283 + 284 + if (!strcmp(led_cdev->default_trigger, "none")) { 285 + led_trigger_remove(led_cdev); 286 + return; 287 + } 291 288 292 289 down_read(&triggers_list_lock); 293 290 down_write(&led_cdev->trigger_lock);
+3 -16
drivers/leds/leds-cros_ec.c
··· 60 60 union cros_ec_led_cmd_data { 61 61 struct ec_params_led_control req; 62 62 struct ec_response_led_control resp; 63 - } __packed; 63 + }; 64 64 65 65 static int cros_ec_led_send_cmd(struct cros_ec_device *cros_ec, 66 66 union cros_ec_led_cmd_data *arg) 67 67 { 68 68 int ret; 69 - struct { 70 - struct cros_ec_command msg; 71 - union cros_ec_led_cmd_data data; 72 - } __packed buf = { 73 - .msg = { 74 - .version = 1, 75 - .command = EC_CMD_LED_CONTROL, 76 - .insize = sizeof(arg->resp), 77 - .outsize = sizeof(arg->req), 78 - }, 79 - .data.req = arg->req 80 - }; 81 69 82 - ret = cros_ec_cmd_xfer_status(cros_ec, &buf.msg); 70 + ret = cros_ec_cmd(cros_ec, 1, EC_CMD_LED_CONTROL, &arg->req, 71 + sizeof(arg->req), &arg->resp, sizeof(arg->resp)); 83 72 if (ret < 0) 84 73 return ret; 85 - 86 - arg->resp = buf.data.resp; 87 74 88 75 return 0; 89 76 }
+49 -163
drivers/leds/leds-lp8860.c
··· 90 90 * @led_dev: led class device pointer 91 91 * @regmap: Devices register map 92 92 * @eeprom_regmap: EEPROM register map 93 - * @enable_gpio: VDDIO/EN gpio to enable communication interface 94 - * @regulator: LED supply regulator pointer 95 93 */ 96 94 struct lp8860_led { 97 95 struct mutex lock; ··· 97 99 struct led_classdev led_dev; 98 100 struct regmap *regmap; 99 101 struct regmap *eeprom_regmap; 100 - struct gpio_desc *enable_gpio; 101 - struct regulator *regulator; 102 102 }; 103 103 104 - struct lp8860_eeprom_reg { 105 - uint8_t reg; 106 - uint8_t value; 107 - }; 108 - 109 - static struct lp8860_eeprom_reg lp8860_eeprom_disp_regs[] = { 104 + static const struct reg_sequence lp8860_eeprom_disp_regs[] = { 110 105 { LP8860_EEPROM_REG_0, 0xed }, 111 106 { LP8860_EEPROM_REG_1, 0xdf }, 112 107 { LP8860_EEPROM_REG_2, 0xdc }, ··· 127 136 { LP8860_EEPROM_REG_24, 0x3E }, 128 137 }; 129 138 130 - static int lp8860_unlock_eeprom(struct lp8860_led *led, int lock) 139 + static int lp8860_unlock_eeprom(struct lp8860_led *led) 131 140 { 132 141 int ret; 133 142 134 - mutex_lock(&led->lock); 143 + guard(mutex)(&led->lock); 135 144 136 - if (lock == LP8860_UNLOCK_EEPROM) { 137 - ret = regmap_write(led->regmap, 138 - LP8860_EEPROM_UNLOCK, 139 - LP8860_EEPROM_CODE_1); 140 - if (ret) { 141 - dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 142 - goto out; 143 - } 144 - 145 - ret = regmap_write(led->regmap, 146 - LP8860_EEPROM_UNLOCK, 147 - LP8860_EEPROM_CODE_2); 148 - if (ret) { 149 - dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 150 - goto out; 151 - } 152 - ret = regmap_write(led->regmap, 153 - LP8860_EEPROM_UNLOCK, 154 - LP8860_EEPROM_CODE_3); 155 - if (ret) { 156 - dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 157 - goto out; 158 - } 159 - } else { 160 - ret = regmap_write(led->regmap, 161 - LP8860_EEPROM_UNLOCK, 162 - LP8860_LOCK_EEPROM); 145 + ret = regmap_write(led->regmap, LP8860_EEPROM_UNLOCK, LP8860_EEPROM_CODE_1); 146 + if (ret) { 147 + dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 148 + return ret; 163 149 } 164 150 165 - out: 166 - mutex_unlock(&led->lock); 151 + ret = regmap_write(led->regmap, LP8860_EEPROM_UNLOCK, LP8860_EEPROM_CODE_2); 152 + if (ret) { 153 + dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 154 + return ret; 155 + } 156 + ret = regmap_write(led->regmap, LP8860_EEPROM_UNLOCK, LP8860_EEPROM_CODE_3); 157 + if (ret) { 158 + dev_err(&led->client->dev, "EEPROM Unlock failed\n"); 159 + return ret; 160 + } 161 + 167 162 return ret; 168 163 } 169 164 ··· 186 209 int disp_brightness = brt_val * 255; 187 210 int ret; 188 211 189 - mutex_lock(&led->lock); 212 + guard(mutex)(&led->lock); 190 213 191 214 ret = lp8860_fault_check(led); 192 215 if (ret) { 193 216 dev_err(&led->client->dev, "Cannot read/clear faults\n"); 194 - goto out; 217 + return ret; 195 218 } 196 219 197 220 ret = regmap_write(led->regmap, LP8860_DISP_CL1_BRT_MSB, 198 221 (disp_brightness & 0xff00) >> 8); 199 222 if (ret) { 200 223 dev_err(&led->client->dev, "Cannot write CL1 MSB\n"); 201 - goto out; 224 + return ret; 202 225 } 203 226 204 227 ret = regmap_write(led->regmap, LP8860_DISP_CL1_BRT_LSB, 205 228 disp_brightness & 0xff); 206 229 if (ret) { 207 230 dev_err(&led->client->dev, "Cannot write CL1 LSB\n"); 208 - goto out; 231 + return ret; 209 232 } 210 - out: 211 - mutex_unlock(&led->lock); 212 - return ret; 233 + 234 + return 0; 213 235 } 214 236 215 237 static int lp8860_init(struct lp8860_led *led) 216 238 { 217 239 unsigned int read_buf; 218 - int ret, i, reg_count; 219 - 220 - if (led->regulator) { 221 - ret = regulator_enable(led->regulator); 222 - if (ret) { 223 - dev_err(&led->client->dev, 224 - "Failed to enable regulator\n"); 225 - return ret; 226 - } 227 - } 228 - 229 - gpiod_direction_output(led->enable_gpio, 1); 240 + int ret, reg_count; 230 241 231 242 ret = lp8860_fault_check(led); 232 243 if (ret) ··· 224 259 if (ret) 225 260 goto out; 226 261 227 - ret = lp8860_unlock_eeprom(led, LP8860_UNLOCK_EEPROM); 262 + ret = lp8860_unlock_eeprom(led); 228 263 if (ret) { 229 264 dev_err(&led->client->dev, "Failed unlocking EEPROM\n"); 230 265 goto out; 231 266 } 232 267 233 268 reg_count = ARRAY_SIZE(lp8860_eeprom_disp_regs); 234 - for (i = 0; i < reg_count; i++) { 235 - ret = regmap_write(led->eeprom_regmap, 236 - lp8860_eeprom_disp_regs[i].reg, 237 - lp8860_eeprom_disp_regs[i].value); 238 - if (ret) { 239 - dev_err(&led->client->dev, "Failed writing EEPROM\n"); 240 - goto out; 241 - } 269 + ret = regmap_multi_reg_write(led->eeprom_regmap, lp8860_eeprom_disp_regs, reg_count); 270 + if (ret) { 271 + dev_err(&led->client->dev, "Failed writing EEPROM\n"); 272 + goto out; 242 273 } 243 274 244 - ret = lp8860_unlock_eeprom(led, LP8860_LOCK_EEPROM); 275 + ret = regmap_write(led->regmap, LP8860_EEPROM_UNLOCK, LP8860_LOCK_EEPROM); 245 276 if (ret) 246 277 goto out; 247 278 ··· 252 291 return ret; 253 292 254 293 out: 255 - if (ret) 256 - gpiod_direction_output(led->enable_gpio, 0); 257 - 258 - if (led->regulator) { 259 - ret = regulator_disable(led->regulator); 260 - if (ret) 261 - dev_err(&led->client->dev, 262 - "Failed to disable regulator\n"); 263 - } 264 - 265 294 return ret; 266 295 } 267 - 268 - static const struct reg_default lp8860_reg_defs[] = { 269 - { LP8860_DISP_CL1_BRT_MSB, 0x00}, 270 - { LP8860_DISP_CL1_BRT_LSB, 0x00}, 271 - { LP8860_DISP_CL1_CURR_MSB, 0x00}, 272 - { LP8860_DISP_CL1_CURR_LSB, 0x00}, 273 - { LP8860_CL2_BRT_MSB, 0x00}, 274 - { LP8860_CL2_BRT_LSB, 0x00}, 275 - { LP8860_CL2_CURRENT, 0x00}, 276 - { LP8860_CL3_BRT_MSB, 0x00}, 277 - { LP8860_CL3_BRT_LSB, 0x00}, 278 - { LP8860_CL3_CURRENT, 0x00}, 279 - { LP8860_CL4_BRT_MSB, 0x00}, 280 - { LP8860_CL4_BRT_LSB, 0x00}, 281 - { LP8860_CL4_CURRENT, 0x00}, 282 - { LP8860_CONFIG, 0x00}, 283 - { LP8860_FAULT_CLEAR, 0x00}, 284 - { LP8860_EEPROM_CNTRL, 0x80}, 285 - { LP8860_EEPROM_UNLOCK, 0x00}, 286 - }; 287 296 288 297 static const struct regmap_config lp8860_regmap_config = { 289 298 .reg_bits = 8, 290 299 .val_bits = 8, 291 300 292 301 .max_register = LP8860_EEPROM_UNLOCK, 293 - .reg_defaults = lp8860_reg_defs, 294 - .num_reg_defaults = ARRAY_SIZE(lp8860_reg_defs), 295 - }; 296 - 297 - static const struct reg_default lp8860_eeprom_defs[] = { 298 - { LP8860_EEPROM_REG_0, 0x00 }, 299 - { LP8860_EEPROM_REG_1, 0x00 }, 300 - { LP8860_EEPROM_REG_2, 0x00 }, 301 - { LP8860_EEPROM_REG_3, 0x00 }, 302 - { LP8860_EEPROM_REG_4, 0x00 }, 303 - { LP8860_EEPROM_REG_5, 0x00 }, 304 - { LP8860_EEPROM_REG_6, 0x00 }, 305 - { LP8860_EEPROM_REG_7, 0x00 }, 306 - { LP8860_EEPROM_REG_8, 0x00 }, 307 - { LP8860_EEPROM_REG_9, 0x00 }, 308 - { LP8860_EEPROM_REG_10, 0x00 }, 309 - { LP8860_EEPROM_REG_11, 0x00 }, 310 - { LP8860_EEPROM_REG_12, 0x00 }, 311 - { LP8860_EEPROM_REG_13, 0x00 }, 312 - { LP8860_EEPROM_REG_14, 0x00 }, 313 - { LP8860_EEPROM_REG_15, 0x00 }, 314 - { LP8860_EEPROM_REG_16, 0x00 }, 315 - { LP8860_EEPROM_REG_17, 0x00 }, 316 - { LP8860_EEPROM_REG_18, 0x00 }, 317 - { LP8860_EEPROM_REG_19, 0x00 }, 318 - { LP8860_EEPROM_REG_20, 0x00 }, 319 - { LP8860_EEPROM_REG_21, 0x00 }, 320 - { LP8860_EEPROM_REG_22, 0x00 }, 321 - { LP8860_EEPROM_REG_23, 0x00 }, 322 - { LP8860_EEPROM_REG_24, 0x00 }, 323 302 }; 324 303 325 304 static const struct regmap_config lp8860_eeprom_regmap_config = { ··· 267 366 .val_bits = 8, 268 367 269 368 .max_register = LP8860_EEPROM_REG_24, 270 - .reg_defaults = lp8860_eeprom_defs, 271 - .num_reg_defaults = ARRAY_SIZE(lp8860_eeprom_defs), 272 369 }; 370 + 371 + static void lp8860_disable_gpio(void *data) 372 + { 373 + struct gpio_desc *gpio = data; 374 + 375 + gpiod_set_value(gpio, 0); 376 + } 273 377 274 378 static int lp8860_probe(struct i2c_client *client) 275 379 { ··· 283 377 struct device_node *np = dev_of_node(&client->dev); 284 378 struct device_node *child_node; 285 379 struct led_init_data init_data = {}; 380 + struct gpio_desc *enable_gpio; 286 381 287 382 led = devm_kzalloc(&client->dev, sizeof(*led), GFP_KERNEL); 288 383 if (!led) ··· 293 386 if (!child_node) 294 387 return -EINVAL; 295 388 296 - led->enable_gpio = devm_gpiod_get_optional(&client->dev, 297 - "enable", GPIOD_OUT_LOW); 298 - if (IS_ERR(led->enable_gpio)) { 299 - ret = PTR_ERR(led->enable_gpio); 300 - dev_err(&client->dev, "Failed to get enable gpio: %d\n", ret); 301 - return ret; 302 - } 389 + enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW); 390 + if (IS_ERR(enable_gpio)) 391 + return dev_err_probe(&client->dev, PTR_ERR(enable_gpio), 392 + "Failed to get enable GPIO\n"); 393 + devm_add_action_or_reset(&client->dev, lp8860_disable_gpio, enable_gpio); 303 394 304 - led->regulator = devm_regulator_get(&client->dev, "vled"); 305 - if (IS_ERR(led->regulator)) 306 - led->regulator = NULL; 395 + ret = devm_regulator_get_enable_optional(&client->dev, "vled"); 396 + if (ret && ret != -ENODEV) 397 + return dev_err_probe(&client->dev, ret, 398 + "Failed to enable vled regulator\n"); 307 399 308 400 led->client = client; 309 401 led->led_dev.brightness_set_blocking = lp8860_brightness_set; 310 402 311 - mutex_init(&led->lock); 312 - 313 - i2c_set_clientdata(client, led); 403 + devm_mutex_init(&client->dev, &led->lock); 314 404 315 405 led->regmap = devm_regmap_init_i2c(client, &lp8860_regmap_config); 316 406 if (IS_ERR(led->regmap)) { ··· 343 439 return 0; 344 440 } 345 441 346 - static void lp8860_remove(struct i2c_client *client) 347 - { 348 - struct lp8860_led *led = i2c_get_clientdata(client); 349 - int ret; 350 - 351 - gpiod_direction_output(led->enable_gpio, 0); 352 - 353 - if (led->regulator) { 354 - ret = regulator_disable(led->regulator); 355 - if (ret) 356 - dev_err(&led->client->dev, 357 - "Failed to disable regulator\n"); 358 - } 359 - 360 - mutex_destroy(&led->lock); 361 - } 362 - 363 442 static const struct i2c_device_id lp8860_id[] = { 364 443 { "lp8860" }, 365 444 { } ··· 361 474 .of_match_table = of_lp8860_leds_match, 362 475 }, 363 476 .probe = lp8860_probe, 364 - .remove = lp8860_remove, 365 477 .id_table = lp8860_id, 366 478 }; 367 479 module_i2c_driver(lp8860_driver);
+6 -5
drivers/leds/leds-pca9532.c
··· 318 318 return -EBUSY; 319 319 } 320 320 321 - static void pca9532_gpio_set_value(struct gpio_chip *gc, unsigned offset, int val) 321 + static int pca9532_gpio_set_value(struct gpio_chip *gc, unsigned int offset, 322 + int val) 322 323 { 323 324 struct pca9532_data *data = gpiochip_get_data(gc); 324 325 struct pca9532_led *led = &data->leds[offset]; ··· 330 329 led->state = PCA9532_OFF; 331 330 332 331 pca9532_setled(led); 332 + 333 + return 0; 333 334 } 334 335 335 336 static int pca9532_gpio_get_value(struct gpio_chip *gc, unsigned offset) ··· 354 351 355 352 static int pca9532_gpio_direction_output(struct gpio_chip *gc, unsigned offset, int val) 356 353 { 357 - pca9532_gpio_set_value(gc, offset, val); 358 - 359 - return 0; 354 + return pca9532_gpio_set_value(gc, offset, val); 360 355 } 361 356 #endif /* CONFIG_LEDS_PCA9532_GPIO */ 362 357 ··· 473 472 data->gpio.label = "gpio-pca9532"; 474 473 data->gpio.direction_input = pca9532_gpio_direction_input; 475 474 data->gpio.direction_output = pca9532_gpio_direction_output; 476 - data->gpio.set = pca9532_gpio_set_value; 475 + data->gpio.set_rv = pca9532_gpio_set_value; 477 476 data->gpio.get = pca9532_gpio_get_value; 478 477 data->gpio.request = pca9532_gpio_request_pin; 479 478 data->gpio.can_sleep = 1;
+13 -15
drivers/leds/leds-pca955x.c
··· 73 73 }; 74 74 75 75 struct pca955x_chipdef { 76 - int bits; 76 + u8 bits; 77 77 u8 slv_addr; /* 7-bit slave address mask */ 78 78 int slv_addr_shift; /* Number of bits to ignore */ 79 79 int blink_div; /* PSC divider */ ··· 142 142 }; 143 143 144 144 /* 8 bits per input register */ 145 - static inline int pca955x_num_input_regs(int bits) 145 + static inline u8 pca955x_num_input_regs(u8 bits) 146 146 { 147 147 return (bits + 7) / 8; 148 148 } 149 149 150 150 /* 4 bits per LED selector register */ 151 - static inline int pca955x_num_led_regs(int bits) 151 + static inline u8 pca955x_num_led_regs(u8 bits) 152 152 { 153 153 return (bits + 3) / 4; 154 154 } ··· 495 495 return pca955x_led_set(&led->led_cdev, PCA955X_GPIO_LOW); 496 496 } 497 497 498 - static void pca955x_gpio_set_value(struct gpio_chip *gc, unsigned int offset, 499 - int val) 498 + static int pca955x_gpio_set_value(struct gpio_chip *gc, unsigned int offset, 499 + int val) 500 500 { 501 - pca955x_set_value(gc, offset, val); 501 + return pca955x_set_value(gc, offset, val); 502 502 } 503 503 504 504 static int pca955x_gpio_get_value(struct gpio_chip *gc, unsigned int offset) ··· 581 581 struct led_classdev *led; 582 582 struct led_init_data init_data; 583 583 struct i2c_adapter *adapter; 584 - int i, bit, err, nls, reg; 584 + u8 i, nls, psc0; 585 585 u8 ls1[4]; 586 586 u8 ls2[4]; 587 587 struct pca955x_platform_data *pdata; 588 - u8 psc0; 589 588 bool keep_psc0 = false; 590 589 bool set_default_label = false; 591 590 char default_label[8]; 591 + int bit, err, reg; 592 592 593 593 chip = i2c_get_match_data(client); 594 594 if (!chip) ··· 610 610 return -ENODEV; 611 611 } 612 612 613 - dev_info(&client->dev, "leds-pca955x: Using %s %d-bit LED driver at " 614 - "slave address 0x%02x\n", client->name, chip->bits, 615 - client->addr); 613 + dev_info(&client->dev, "Using %s %u-bit LED driver at slave address 0x%02x\n", 614 + client->name, chip->bits, client->addr); 616 615 617 616 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 618 617 return -EIO; 619 618 620 619 if (pdata->num_leds != chip->bits) { 621 620 dev_err(&client->dev, 622 - "board info claims %d LEDs on a %d-bit chip\n", 621 + "board info claims %d LEDs on a %u-bit chip\n", 623 622 pdata->num_leds, chip->bits); 624 623 return -ENODEV; 625 624 } ··· 693 694 } 694 695 695 696 if (set_default_label) { 696 - snprintf(default_label, sizeof(default_label), 697 - "%d", i); 697 + snprintf(default_label, sizeof(default_label), "%u", i); 698 698 init_data.default_label = default_label; 699 699 } else { 700 700 init_data.default_label = NULL; ··· 737 739 pca955x->gpio.label = "gpio-pca955x"; 738 740 pca955x->gpio.direction_input = pca955x_gpio_direction_input; 739 741 pca955x->gpio.direction_output = pca955x_gpio_direction_output; 740 - pca955x->gpio.set = pca955x_gpio_set_value; 742 + pca955x->gpio.set_rv = pca955x_gpio_set_value; 741 743 pca955x->gpio.get = pca955x_gpio_get_value; 742 744 pca955x->gpio.request = pca955x_gpio_request_pin; 743 745 pca955x->gpio.free = pca955x_gpio_free_pin;
+1 -1
drivers/leds/leds-pca995x.c
··· 197 197 198 198 static const struct of_device_id pca995x_of_match[] = { 199 199 { .compatible = "nxp,pca9952", .data = &pca9952_chipdef }, 200 - { .compatible = "nxp,pca9955b", . data = &pca9955b_chipdef }, 200 + { .compatible = "nxp,pca9955b", .data = &pca9955b_chipdef }, 201 201 { .compatible = "nxp,pca9956b", .data = &pca9956b_chipdef }, 202 202 {}, 203 203 };
+6 -5
drivers/leds/leds-tca6507.c
··· 588 588 } 589 589 590 590 #ifdef CONFIG_GPIOLIB 591 - static void tca6507_gpio_set_value(struct gpio_chip *gc, 592 - unsigned offset, int val) 591 + static int tca6507_gpio_set_value(struct gpio_chip *gc, unsigned int offset, 592 + int val) 593 593 { 594 594 struct tca6507_chip *tca = gpiochip_get_data(gc); 595 595 unsigned long flags; ··· 604 604 spin_unlock_irqrestore(&tca->lock, flags); 605 605 if (tca->reg_set) 606 606 schedule_work(&tca->work); 607 + 608 + return 0; 607 609 } 608 610 609 611 static int tca6507_gpio_direction_output(struct gpio_chip *gc, 610 612 unsigned offset, int val) 611 613 { 612 - tca6507_gpio_set_value(gc, offset, val); 613 - return 0; 614 + return tca6507_gpio_set_value(gc, offset, val); 614 615 } 615 616 616 617 static int tca6507_probe_gpios(struct device *dev, ··· 637 636 tca->gpio.base = -1; 638 637 tca->gpio.owner = THIS_MODULE; 639 638 tca->gpio.direction_output = tca6507_gpio_direction_output; 640 - tca->gpio.set = tca6507_gpio_set_value; 639 + tca->gpio.set_rv = tca6507_gpio_set_value; 641 640 tca->gpio.parent = dev; 642 641 err = devm_gpiochip_add_data(dev, &tca->gpio, tca); 643 642 if (err) {
+2 -2
drivers/leds/leds-turris-omnia.c
··· 361 361 static struct attribute *omnia_led_controller_attrs[] = { 362 362 &dev_attr_brightness.attr, 363 363 &dev_attr_gamma_correction.attr, 364 - NULL, 364 + NULL 365 365 }; 366 366 ATTRIBUTE_GROUPS(omnia_led_controller); 367 367 ··· 527 527 528 528 static const struct of_device_id of_omnia_leds_match[] = { 529 529 { .compatible = "cznic,turris-omnia-leds", }, 530 - {}, 530 + { } 531 531 }; 532 532 MODULE_DEVICE_TABLE(of, of_omnia_leds_match); 533 533
+8 -8
drivers/leds/rgb/leds-mt6370-rgb.c
··· 199 199 200 200 /* Current unit: microamp, time unit: millisecond */ 201 201 static const struct linear_range common_led_ranges[R_MAX_RANGES] = { 202 - [R_LED123_CURR] = { 4000, 1, 6, 4000 }, 203 - [R_LED4_CURR] = { 2000, 1, 3, 2000 }, 204 - [R_LED_TRFON] = { 125, 0, 15, 200 }, 205 - [R_LED_TOFF] = { 250, 0, 15, 400 }, 202 + [R_LED123_CURR] = LINEAR_RANGE(4000, 1, 6, 4000), 203 + [R_LED4_CURR] = LINEAR_RANGE(2000, 1, 3, 2000), 204 + [R_LED_TRFON] = LINEAR_RANGE(125, 0, 15, 200), 205 + [R_LED_TOFF] = LINEAR_RANGE(250, 0, 15, 400), 206 206 }; 207 207 208 208 static const struct linear_range mt6372_led_ranges[R_MAX_RANGES] = { 209 - [R_LED123_CURR] = { 2000, 1, 14, 2000 }, 210 - [R_LED4_CURR] = { 2000, 1, 14, 2000 }, 211 - [R_LED_TRFON] = { 125, 0, 15, 250 }, 212 - [R_LED_TOFF] = { 250, 0, 15, 500 }, 209 + [R_LED123_CURR] = LINEAR_RANGE(2000, 1, 14, 2000), 210 + [R_LED4_CURR] = LINEAR_RANGE(2000, 1, 14, 2000), 211 + [R_LED_TRFON] = LINEAR_RANGE(125, 0, 15, 250), 212 + [R_LED_TOFF] = LINEAR_RANGE(250, 0, 15, 500), 213 213 }; 214 214 215 215 static const unsigned int common_tfreqs[] = {
+2 -3
drivers/leds/rgb/leds-ncp5623.c
··· 155 155 struct device *dev = &client->dev; 156 156 struct fwnode_handle *mc_node, *led_node; 157 157 struct led_init_data init_data = { }; 158 - int num_subleds = 0; 159 158 struct ncp5623 *ncp; 160 159 struct mc_subled *subled_info; 160 + unsigned int num_subleds; 161 161 u32 color_index; 162 162 u32 reg; 163 163 int ret; ··· 172 172 if (!mc_node) 173 173 return -EINVAL; 174 174 175 - fwnode_for_each_child_node(mc_node, led_node) 176 - num_subleds++; 175 + num_subleds = fwnode_get_child_node_count(mc_node); 177 176 178 177 subled_info = devm_kcalloc(dev, num_subleds, sizeof(*subled_info), GFP_KERNEL); 179 178 if (!subled_info) {
+3 -4
drivers/leds/rgb/leds-pwm-multicolor.c
··· 107 107 108 108 static int led_pwm_mc_probe(struct platform_device *pdev) 109 109 { 110 - struct fwnode_handle *mcnode, *fwnode; 110 + struct fwnode_handle *mcnode; 111 111 struct led_init_data init_data = {}; 112 112 struct led_classdev *cdev; 113 113 struct mc_subled *subled; 114 114 struct pwm_mc_led *priv; 115 - int count = 0; 115 + unsigned int count; 116 116 int ret = 0; 117 117 118 118 mcnode = device_get_named_child_node(&pdev->dev, "multi-led"); ··· 121 121 "expected multi-led node\n"); 122 122 123 123 /* count the nodes inside the multi-led node */ 124 - fwnode_for_each_child_node(mcnode, fwnode) 125 - count++; 124 + count = fwnode_get_child_node_count(mcnode); 126 125 127 126 priv = devm_kzalloc(&pdev->dev, struct_size(priv, leds, count), 128 127 GFP_KERNEL);
+2 -4
drivers/usb/typec/tcpm/tcpm.c
··· 7166 7166 7167 7167 static int tcpm_fw_get_caps(struct tcpm_port *port, struct fwnode_handle *fwnode) 7168 7168 { 7169 - struct fwnode_handle *capabilities, *child, *caps = NULL; 7169 + struct fwnode_handle *capabilities, *caps = NULL; 7170 7170 unsigned int nr_src_pdo, nr_snk_pdo; 7171 7171 const char *opmode_str; 7172 7172 u32 *src_pdo, *snk_pdo; ··· 7232 7232 if (!capabilities) { 7233 7233 port->pd_count = 1; 7234 7234 } else { 7235 - fwnode_for_each_child_node(capabilities, child) 7236 - port->pd_count++; 7237 - 7235 + port->pd_count = fwnode_get_child_node_count(capabilities); 7238 7236 if (!port->pd_count) { 7239 7237 ret = -ENODATA; 7240 7238 goto put_capabilities;
+16
include/linux/led-class-flash.h
··· 45 45 int (*timeout_set)(struct led_classdev_flash *fled_cdev, u32 timeout); 46 46 /* get the flash LED fault */ 47 47 int (*fault_get)(struct led_classdev_flash *fled_cdev, u32 *fault); 48 + /* set flash duration */ 49 + int (*duration_set)(struct led_classdev_flash *fled_cdev, u32 duration); 48 50 }; 49 51 50 52 /* ··· 76 74 77 75 /* flash timeout value in microseconds along with its constraints */ 78 76 struct led_flash_setting timeout; 77 + 78 + /* flash timeout value in microseconds along with its constraints */ 79 + struct led_flash_setting duration; 79 80 80 81 /* LED Flash class sysfs groups */ 81 82 const struct attribute_group *sysfs_groups[LED_FLASH_SYSFS_GROUPS_SIZE]; ··· 213 208 * Returns: 0 on success or negative error value on failure 214 209 */ 215 210 int led_get_flash_fault(struct led_classdev_flash *fled_cdev, u32 *fault); 211 + 212 + /** 213 + * led_set_flash_duration - set flash LED duration 214 + * @fled_cdev: the flash LED to set 215 + * @timeout: the flash duration to set it to 216 + * 217 + * Set the flash strobe duration. 218 + * 219 + * Returns: 0 on success or negative error value on failure 220 + */ 221 + int led_set_flash_duration(struct led_classdev_flash *fled_cdev, u32 duration); 216 222 217 223 #endif /* __LINUX_FLASH_LEDS_H_INCLUDED */
+6 -1
include/linux/property.h
··· 208 208 int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index); 209 209 int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name); 210 210 211 - unsigned int device_get_child_node_count(const struct device *dev); 211 + unsigned int fwnode_get_child_node_count(const struct fwnode_handle *fwnode); 212 + 213 + static inline unsigned int device_get_child_node_count(const struct device *dev) 214 + { 215 + return fwnode_get_child_node_count(dev_fwnode(dev)); 216 + } 212 217 213 218 static inline int device_property_read_u8(const struct device *dev, 214 219 const char *propname, u8 *val)