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

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

Pull LED updates from Lee Jones:

- pca955x: Add HW blink support, utilizing PWM0. It supports one
frequency across all blinking LEDs and falls back to software blink
if different frequencies are requested.

- trigger: netdev: Allow configuring LED blink interval via .blink_set
even when HW offload (.hw_control) is enabled.

- led-core: Fix a race condition where a quick LED_OFF followed by
another brightness set could leave the LED off incorrectly,
especially noticeable after the introduction of the ordered
workqueue.

- qcom-lpg: Add support for 6-bit PWM resolution alongside the existing
9-bit support.

- qcom-lpg: Fix PWM value capping to respect the selected resolution
(6-bit or 9-bit) for normal PWMs.

- qcom-lpg: Fix PWM value capping to respect the selected resolution
for Hi-Res PWMs.

- qcom-lpg: Fix calculation of the best period for Hi-Res PWMs to
prevent requested duty cycles from exceeding the maximum allowed by
the selected resolution.

- st1202: Add a check for the error code returned by devm_mutex_init().

- pwm-multicolor: Add a check for the return value of
fwnode_property_read_u32().

- st1202: Ensure hardware initialization (st1202_setup) happens before
DT node processing (st1202_dt_init).

- Kconfig: leds-st1202: Add select LEDS_TRIGGER_PATTERN as it's
required by the driver.

- lp8860: Drop unneeded explicit assignment to REGCACHE_NONE.

- pca955x: Refactor code with helper functions and rename some
functions/variables for clarity.

- pca955x: Pass driver data pointers instead of the I2C client to
helper functions.

- pca955x: Optimize probe LED selection logic to reduce I2C operations.

- pca955x: Revert the removal of pca95xx_num_led_regs() (renaming it to
pca955x_num_led_regs) as it's needed for HW blink support.

- st1202: Refactor st1202_led_set() to use the !! operator for boolean
conversion.

- st1202: Minor spacing and proofreading edits in comments.

- Directory Rename: Rename the drivers/leds/simple directory to
drivers/leds/simatic as the drivers within are not simple.

- mlxcpld: Remove unused include of acpi.h.

- nic78bx: Tidy up the ACPI ID table (remove ACPI_PTR, use
mod_devicetable.h, remove explicit driver_data initializer).

- tlc591xx: Convert text binding to YAML format, add child node
constraints, and fix typos/formatting in the example.

- qcom-lpg: Document the qcom,pm8937-pwm compatible string as a
fallback for qcom,pm8916-pwm.

* tag 'leds-next-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/leds: (23 commits)
leds: nic78bx: Tidy up ACPI ID table
leds: mlxcpld: Remove unused ACPI header inclusion
leds: rgb: leds-qcom-lpg: Fix calculation of best period Hi-Res PWMs
leds: rgb: leds-qcom-lpg: Fix pwm resolution max for Hi-Res PWMs
leds: rgb: leds-qcom-lpg: Fix pwm resolution max for normal PWMs
leds: Rename simple directory to simatic
leds: Kconfig: leds-st1202: Add select for required LEDS_TRIGGER_PATTERN
leds: leds-st1202: Spacing and proofreading editing
leds: leds-st1202: Initialize hardware before DT node child operations
leds: pwm-multicolor: Add check for fwnode_property_read_u32
leds: rgb: leds-qcom-lpg: Add support for 6-bit PWM resolution
leds: Fix LED_OFF brightness race
Revert "leds-pca955x: Remove the unused function pca95xx_num_led_regs()"
leds: st1202: Refactor st1202_led_set() to use !! operator for boolean conversion
dt-bindings: leds: qcom-lpg: Document PM8937 PWM compatible
leds: pca955x: Add HW blink support
leds: pca955x: Optimize probe LED selection
leds: pca955x: Use pointers to driver data rather than I2C client
leds: pca955x: Refactor with helper functions and renaming
dt-bindings: leds: Convert leds-tlc591xx.txt to yaml format
...

+418 -193
+4
Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
··· 39 39 - enum: 40 40 - qcom,pm8550-pwm 41 41 - const: qcom,pm8350c-pwm 42 + - items: 43 + - enum: 44 + - qcom,pm8937-pwm 45 + - const: qcom,pm8916-pwm 42 46 43 47 "#pwm-cells": 44 48 const: 2
-40
Documentation/devicetree/bindings/leds/leds-tlc591xx.txt
··· 1 - LEDs connected to tlc59116 or tlc59108 2 - 3 - Required properties 4 - - compatible: should be "ti,tlc59116" or "ti,tlc59108" 5 - - #address-cells: must be 1 6 - - #size-cells: must be 0 7 - - reg: typically 0x68 8 - 9 - Each led is represented as a sub-node of the ti,tlc59116. 10 - See Documentation/devicetree/bindings/leds/common.txt 11 - 12 - LED sub-node properties: 13 - - reg: number of LED line, 0 to 15 or 0 to 7 14 - - label: (optional) name of LED 15 - - linux,default-trigger : (optional) 16 - 17 - Examples: 18 - 19 - tlc59116@68 { 20 - #address-cells = <1>; 21 - #size-cells = <0>; 22 - compatible = "ti,tlc59116"; 23 - reg = <0x68>; 24 - 25 - wan@0 { 26 - label = "wrt1900ac:amber:wan"; 27 - reg = <0x0>; 28 - }; 29 - 30 - 2g@2 { 31 - label = "wrt1900ac:white:2g"; 32 - reg = <0x2>; 33 - }; 34 - 35 - alive@9 { 36 - label = "wrt1900ac:green:alive"; 37 - reg = <0x9>; 38 - linux,default_trigger = "heartbeat"; 39 - }; 40 - };
+90
Documentation/devicetree/bindings/leds/ti,tlc59116.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,tlc59116.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: LEDs connected to tlc59116 or tlc59108 8 + 9 + maintainers: 10 + - Andrew Lunn <andrew@lunn.ch> 11 + 12 + properties: 13 + compatible: 14 + enum: 15 + - ti,tlc59108 16 + - ti,tlc59116 17 + 18 + reg: 19 + maxItems: 1 20 + 21 + "#address-cells": 22 + const: 1 23 + 24 + "#size-cells": 25 + const: 0 26 + 27 + patternProperties: 28 + "^led@[0-9a-f]$": 29 + type: object 30 + $ref: common.yaml# 31 + properties: 32 + reg: 33 + items: 34 + minimum: 0 35 + maximum: 15 36 + 37 + unevaluatedProperties: false 38 + 39 + required: 40 + - compatible 41 + - reg 42 + - "#address-cells" 43 + - "#size-cells" 44 + 45 + allOf: 46 + - if: 47 + properties: 48 + compatible: 49 + contains: 50 + const: ti,tlc59108 51 + then: 52 + patternProperties: 53 + "^led@[0-9a-f]$": 54 + properties: 55 + reg: 56 + items: 57 + maximum: 7 58 + 59 + additionalProperties: false 60 + 61 + examples: 62 + - | 63 + i2c { 64 + #address-cells = <1>; 65 + #size-cells = <0>; 66 + 67 + led-controller@68 { 68 + compatible = "ti,tlc59116"; 69 + reg = <0x68>; 70 + #address-cells = <1>; 71 + #size-cells = <0>; 72 + 73 + led@0 { 74 + reg = <0x0>; 75 + label = "wrt1900ac:amber:wan"; 76 + }; 77 + 78 + led@2 { 79 + reg = <0x2>; 80 + label = "wrt1900ac:white:2g"; 81 + }; 82 + 83 + led@9 { 84 + reg = <0x9>; 85 + label = "wrt1900ac:green:alive"; 86 + linux,default-trigger = "heartbeat"; 87 + }; 88 + }; 89 + }; 90 +
+5 -3
drivers/leds/Kconfig
··· 932 932 config LEDS_NIC78BX 933 933 tristate "LED support for NI PXI NIC78bx devices" 934 934 depends on LEDS_CLASS 935 - depends on X86 && ACPI 935 + depends on HAS_IOPORT 936 + depends on X86 || COMPILE_TEST 936 937 help 937 938 This option enables support for the User1 and User2 LEDs on NI 938 939 PXI NIC78bx devices. ··· 980 979 depends on I2C 981 980 depends on OF 982 981 select LEDS_TRIGGERS 982 + select LEDS_TRIGGER_PATTERN 983 983 help 984 984 Say Y to enable support for LEDs connected to LED1202 985 985 LED driver chips accessed via the I2C bus. ··· 1024 1022 comment "LED Triggers" 1025 1023 source "drivers/leds/trigger/Kconfig" 1026 1024 1027 - comment "Simple LED drivers" 1028 - source "drivers/leds/simple/Kconfig" 1025 + comment "Simatic LED drivers" 1026 + source "drivers/leds/simatic/Kconfig" 1029 1027 1030 1028 endif # NEW_LEDS
+2 -2
drivers/leds/Makefile
··· 122 122 # LED Blink 123 123 obj-y += blink/ 124 124 125 - # Simple LED drivers 126 - obj-y += simple/ 125 + # Simatic LED drivers 126 + obj-y += simatic/
+18 -4
drivers/leds/led-core.c
··· 159 159 * before this work item runs once. To make sure this works properly 160 160 * handle LED_SET_BRIGHTNESS_OFF first. 161 161 */ 162 - if (test_and_clear_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags)) 162 + if (test_and_clear_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags)) { 163 163 set_brightness_delayed_set_brightness(led_cdev, LED_OFF); 164 + /* 165 + * The consecutives led_set_brightness(LED_OFF), 166 + * led_set_brightness(LED_FULL) could have been executed out of 167 + * order (LED_FULL first), if the work_flags has been set 168 + * between LED_SET_BRIGHTNESS_OFF and LED_SET_BRIGHTNESS of this 169 + * work. To avoid ending with the LED turned off, turn the LED 170 + * on again. 171 + */ 172 + if (led_cdev->delayed_set_value != LED_OFF) 173 + set_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags); 174 + } 164 175 165 176 if (test_and_clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags)) 166 177 set_brightness_delayed_set_brightness(led_cdev, led_cdev->delayed_set_value); ··· 342 331 * change is done immediately afterwards (before the work runs), 343 332 * it uses a separate work_flag. 344 333 */ 345 - if (value) { 346 - led_cdev->delayed_set_value = value; 334 + led_cdev->delayed_set_value = value; 335 + /* Ensure delayed_set_value is seen before work_flags modification */ 336 + smp_mb__before_atomic(); 337 + 338 + if (value) 347 339 set_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags); 348 - } else { 340 + else { 349 341 clear_bit(LED_SET_BRIGHTNESS, &led_cdev->work_flags); 350 342 clear_bit(LED_SET_BLINK, &led_cdev->work_flags); 351 343 set_bit(LED_SET_BRIGHTNESS_OFF, &led_cdev->work_flags);
-2
drivers/leds/leds-lp8860.c
··· 331 331 .max_register = LP8860_EEPROM_UNLOCK, 332 332 .reg_defaults = lp8860_reg_defs, 333 333 .num_reg_defaults = ARRAY_SIZE(lp8860_reg_defs), 334 - .cache_type = REGCACHE_NONE, 335 334 }; 336 335 337 336 static const struct reg_default lp8860_eeprom_defs[] = { ··· 368 369 .max_register = LP8860_EEPROM_REG_24, 369 370 .reg_defaults = lp8860_eeprom_defs, 370 371 .num_reg_defaults = ARRAY_SIZE(lp8860_eeprom_defs), 371 - .cache_type = REGCACHE_NONE, 372 372 }; 373 373 374 374 static int lp8860_probe(struct i2c_client *client)
-1
drivers/leds/leds-mlxcpld.c
··· 32 32 * POSSIBILITY OF SUCH DAMAGE. 33 33 */ 34 34 35 - #include <linux/acpi.h> 36 35 #include <linux/device.h> 37 36 #include <linux/dmi.h> 38 37 #include <linux/hwmon.h>
+12 -4
drivers/leds/leds-nic78bx.c
··· 3 3 * Copyright (C) 2016 National Instruments Corp. 4 4 */ 5 5 6 - #include <linux/acpi.h> 6 + #include <linux/array_size.h> 7 + #include <linux/bits.h> 8 + #include <linux/container_of.h> 9 + #include <linux/device.h> 10 + #include <linux/errno.h> 11 + #include <linux/io.h> 12 + #include <linux/ioport.h> 7 13 #include <linux/leds.h> 14 + #include <linux/mod_devicetable.h> 8 15 #include <linux/module.h> 9 16 #include <linux/platform_device.h> 10 17 #include <linux/spinlock.h> 18 + #include <linux/types.h> 11 19 12 20 #define NIC78BX_USER1_LED_MASK 0x3 13 21 #define NIC78BX_USER1_GREEN_LED BIT(0) ··· 189 181 } 190 182 191 183 static const struct acpi_device_id led_device_ids[] = { 192 - {"NIC78B3", 0}, 193 - {"", 0}, 184 + { "NIC78B3" }, 185 + { } 194 186 }; 195 187 MODULE_DEVICE_TABLE(acpi, led_device_ids); 196 188 ··· 198 190 .probe = nic78bx_probe, 199 191 .driver = { 200 192 .name = KBUILD_MODNAME, 201 - .acpi_match_table = ACPI_PTR(led_device_ids), 193 + .acpi_match_table = led_device_ids, 202 194 }, 203 195 }; 204 196
+247 -112
drivers/leds/leds-pca955x.c
··· 62 62 #define PCA955X_GPIO_HIGH LED_OFF 63 63 #define PCA955X_GPIO_LOW LED_FULL 64 64 65 + #define PCA955X_BLINK_DEFAULT_MS 1000 66 + 65 67 enum pca955x_type { 66 68 pca9550, 67 69 pca9551, ··· 76 74 int bits; 77 75 u8 slv_addr; /* 7-bit slave address mask */ 78 76 int slv_addr_shift; /* Number of bits to ignore */ 77 + int blink_div; /* PSC divider */ 79 78 }; 80 79 81 80 static const struct pca955x_chipdef pca955x_chipdefs[] = { ··· 84 81 .bits = 2, 85 82 .slv_addr = /* 110000x */ 0x60, 86 83 .slv_addr_shift = 1, 84 + .blink_div = 44, 87 85 }, 88 86 [pca9551] = { 89 87 .bits = 8, 90 88 .slv_addr = /* 1100xxx */ 0x60, 91 89 .slv_addr_shift = 3, 90 + .blink_div = 38, 92 91 }, 93 92 [pca9552] = { 94 93 .bits = 16, 95 94 .slv_addr = /* 1100xxx */ 0x60, 96 95 .slv_addr_shift = 3, 96 + .blink_div = 44, 97 97 }, 98 98 [ibm_pca9552] = { 99 99 .bits = 16, 100 100 .slv_addr = /* 0110xxx */ 0x30, 101 101 .slv_addr_shift = 3, 102 + .blink_div = 44, 102 103 }, 103 104 [pca9553] = { 104 105 .bits = 4, 105 106 .slv_addr = /* 110001x */ 0x62, 106 107 .slv_addr_shift = 1, 108 + .blink_div = 44, 107 109 }, 108 110 }; 109 111 ··· 117 109 struct pca955x_led *leds; 118 110 const struct pca955x_chipdef *chipdef; 119 111 struct i2c_client *client; 112 + unsigned long active_blink; 120 113 unsigned long active_pins; 114 + unsigned long blink_period; 121 115 #ifdef CONFIG_LEDS_PCA955X_GPIO 122 116 struct gpio_chip gpio; 123 117 #endif ··· 134 124 struct fwnode_handle *fwnode; 135 125 }; 136 126 127 + #define led_to_pca955x(l) container_of(l, struct pca955x_led, led_cdev) 128 + 137 129 struct pca955x_platform_data { 138 130 struct pca955x_led *leds; 139 131 int num_leds; 140 132 }; 141 133 142 134 /* 8 bits per input register */ 143 - static inline int pca95xx_num_input_regs(int bits) 135 + static inline int pca955x_num_input_regs(int bits) 144 136 { 145 137 return (bits + 7) / 8; 138 + } 139 + 140 + /* 4 bits per LED selector register */ 141 + static inline int pca955x_num_led_regs(int bits) 142 + { 143 + return (bits + 3) / 4; 146 144 } 147 145 148 146 /* ··· 163 145 ((state & 0x3) << (led_num << 1)); 164 146 } 165 147 148 + static inline int pca955x_ledstate(u8 ls, int led_num) 149 + { 150 + return (ls >> (led_num << 1)) & 0x3; 151 + } 152 + 166 153 /* 167 154 * Write to frequency prescaler register, used to program the 168 - * period of the PWM output. period = (PSCx + 1) / 38 155 + * period of the PWM output. period = (PSCx + 1) / coeff 156 + * Where for pca9551 chips coeff = 38 and for all other chips coeff = 44 169 157 */ 170 - static int pca955x_write_psc(struct i2c_client *client, int n, u8 val) 158 + static int pca955x_write_psc(struct pca955x *pca955x, int n, u8 val) 171 159 { 172 - struct pca955x *pca955x = i2c_get_clientdata(client); 173 - u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + (2 * n); 160 + u8 cmd = pca955x_num_input_regs(pca955x->chipdef->bits) + (2 * n); 174 161 int ret; 175 162 176 - ret = i2c_smbus_write_byte_data(client, cmd, val); 163 + ret = i2c_smbus_write_byte_data(pca955x->client, cmd, val); 177 164 if (ret < 0) 178 - dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", 179 - __func__, n, val, ret); 165 + dev_err(&pca955x->client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", __func__, n, 166 + val, ret); 180 167 return ret; 181 168 } 182 169 ··· 192 169 * 193 170 * Duty cycle is (256 - PWMx) / 256 194 171 */ 195 - static int pca955x_write_pwm(struct i2c_client *client, int n, u8 val) 172 + static int pca955x_write_pwm(struct pca955x *pca955x, int n, u8 val) 196 173 { 197 - struct pca955x *pca955x = i2c_get_clientdata(client); 198 - u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + (2 * n); 174 + u8 cmd = pca955x_num_input_regs(pca955x->chipdef->bits) + 1 + (2 * n); 199 175 int ret; 200 176 201 - ret = i2c_smbus_write_byte_data(client, cmd, val); 177 + ret = i2c_smbus_write_byte_data(pca955x->client, cmd, val); 202 178 if (ret < 0) 203 - dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", 204 - __func__, n, val, ret); 179 + dev_err(&pca955x->client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", __func__, n, 180 + val, ret); 205 181 return ret; 206 182 } 207 183 ··· 208 186 * Write to LED selector register, which determines the source that 209 187 * drives the LED output. 210 188 */ 211 - static int pca955x_write_ls(struct i2c_client *client, int n, u8 val) 189 + static int pca955x_write_ls(struct pca955x *pca955x, int n, u8 val) 212 190 { 213 - struct pca955x *pca955x = i2c_get_clientdata(client); 214 - u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n; 191 + u8 cmd = pca955x_num_input_regs(pca955x->chipdef->bits) + 4 + n; 215 192 int ret; 216 193 217 - ret = i2c_smbus_write_byte_data(client, cmd, val); 194 + ret = i2c_smbus_write_byte_data(pca955x->client, cmd, val); 218 195 if (ret < 0) 219 - dev_err(&client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", 220 - __func__, n, val, ret); 196 + dev_err(&pca955x->client->dev, "%s: reg 0x%x, val 0x%x, err %d\n", __func__, n, 197 + val, ret); 221 198 return ret; 222 199 } 223 200 ··· 224 203 * Read the LED selector register, which determines the source that 225 204 * drives the LED output. 226 205 */ 227 - static int pca955x_read_ls(struct i2c_client *client, int n, u8 *val) 206 + static int pca955x_read_ls(struct pca955x *pca955x, int n, u8 *val) 228 207 { 229 - struct pca955x *pca955x = i2c_get_clientdata(client); 230 - u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n; 208 + u8 cmd = pca955x_num_input_regs(pca955x->chipdef->bits) + 4 + n; 231 209 int ret; 232 210 233 - ret = i2c_smbus_read_byte_data(client, cmd); 211 + ret = i2c_smbus_read_byte_data(pca955x->client, cmd); 234 212 if (ret < 0) { 235 - dev_err(&client->dev, "%s: reg 0x%x, err %d\n", 236 - __func__, n, ret); 213 + dev_err(&pca955x->client->dev, "%s: reg 0x%x, err %d\n", __func__, n, ret); 237 214 return ret; 238 215 } 239 216 *val = (u8)ret; 240 217 return 0; 241 218 } 242 219 243 - static int pca955x_read_pwm(struct i2c_client *client, int n, u8 *val) 220 + static int pca955x_read_pwm(struct pca955x *pca955x, int n, u8 *val) 244 221 { 245 - struct pca955x *pca955x = i2c_get_clientdata(client); 246 - u8 cmd = pca95xx_num_input_regs(pca955x->chipdef->bits) + 1 + (2 * n); 222 + u8 cmd = pca955x_num_input_regs(pca955x->chipdef->bits) + 1 + (2 * n); 247 223 int ret; 248 224 249 - ret = i2c_smbus_read_byte_data(client, cmd); 225 + ret = i2c_smbus_read_byte_data(pca955x->client, cmd); 250 226 if (ret < 0) { 251 - dev_err(&client->dev, "%s: reg 0x%x, err %d\n", 252 - __func__, n, ret); 227 + dev_err(&pca955x->client->dev, "%s: reg 0x%x, err %d\n", __func__, n, ret); 228 + return ret; 229 + } 230 + *val = (u8)ret; 231 + return 0; 232 + } 233 + 234 + static int pca955x_read_psc(struct pca955x *pca955x, int n, u8 *val) 235 + { 236 + int ret; 237 + u8 cmd; 238 + 239 + cmd = pca955x_num_input_regs(pca955x->chipdef->bits) + (2 * n); 240 + ret = i2c_smbus_read_byte_data(pca955x->client, cmd); 241 + if (ret < 0) { 242 + dev_err(&pca955x->client->dev, "%s: reg 0x%x, err %d\n", __func__, n, ret); 253 243 return ret; 254 244 } 255 245 *val = (u8)ret; ··· 269 237 270 238 static enum led_brightness pca955x_led_get(struct led_classdev *led_cdev) 271 239 { 272 - struct pca955x_led *pca955x_led = container_of(led_cdev, 273 - struct pca955x_led, 274 - led_cdev); 240 + struct pca955x_led *pca955x_led = led_to_pca955x(led_cdev); 275 241 struct pca955x *pca955x = pca955x_led->pca955x; 276 242 u8 ls, pwm; 277 243 int ret; 278 244 279 - ret = pca955x_read_ls(pca955x->client, pca955x_led->led_num / 4, &ls); 245 + ret = pca955x_read_ls(pca955x, pca955x_led->led_num / 4, &ls); 280 246 if (ret) 281 247 return ret; 282 248 283 - ls = (ls >> ((pca955x_led->led_num % 4) << 1)) & 0x3; 284 - switch (ls) { 249 + switch (pca955x_ledstate(ls, pca955x_led->led_num % 4)) { 285 250 case PCA955X_LS_LED_ON: 251 + case PCA955X_LS_BLINK0: 286 252 ret = LED_FULL; 287 253 break; 288 254 case PCA955X_LS_LED_OFF: 289 255 ret = LED_OFF; 290 256 break; 291 - case PCA955X_LS_BLINK0: 292 - ret = LED_HALF; 293 - break; 294 257 case PCA955X_LS_BLINK1: 295 - ret = pca955x_read_pwm(pca955x->client, 1, &pwm); 258 + ret = pca955x_read_pwm(pca955x, 1, &pwm); 296 259 if (ret) 297 260 return ret; 298 261 ret = 255 - pwm; ··· 300 273 static int pca955x_led_set(struct led_classdev *led_cdev, 301 274 enum led_brightness value) 302 275 { 303 - struct pca955x_led *pca955x_led; 304 - struct pca955x *pca955x; 276 + struct pca955x_led *pca955x_led = led_to_pca955x(led_cdev); 277 + struct pca955x *pca955x = pca955x_led->pca955x; 278 + int reg = pca955x_led->led_num / 4; 279 + int bit = pca955x_led->led_num % 4; 305 280 u8 ls; 306 - int chip_ls; /* which LSx to use (0-3 potentially) */ 307 - int ls_led; /* which set of bits within LSx to use (0-3) */ 308 281 int ret; 309 - 310 - pca955x_led = container_of(led_cdev, struct pca955x_led, led_cdev); 311 - pca955x = pca955x_led->pca955x; 312 - 313 - chip_ls = pca955x_led->led_num / 4; 314 - ls_led = pca955x_led->led_num % 4; 315 282 316 283 mutex_lock(&pca955x->lock); 317 284 318 - ret = pca955x_read_ls(pca955x->client, chip_ls, &ls); 285 + ret = pca955x_read_ls(pca955x, reg, &ls); 319 286 if (ret) 320 287 goto out; 321 288 322 - switch (value) { 323 - case LED_FULL: 324 - ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON); 325 - break; 326 - case LED_OFF: 327 - ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_OFF); 328 - break; 329 - case LED_HALF: 330 - ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK0); 331 - break; 332 - default: 333 - /* 334 - * Use PWM1 for all other values. This has the unwanted 335 - * side effect of making all LEDs on the chip share the 336 - * same brightness level if set to a value other than 337 - * OFF, HALF, or FULL. But, this is probably better than 338 - * just turning off for all other values. 339 - */ 340 - ret = pca955x_write_pwm(pca955x->client, 1, 255 - value); 341 - if (ret) 289 + if (test_bit(pca955x_led->led_num, &pca955x->active_blink)) { 290 + if (value == LED_OFF) { 291 + clear_bit(pca955x_led->led_num, &pca955x->active_blink); 292 + ls = pca955x_ledsel(ls, bit, PCA955X_LS_LED_OFF); 293 + } else { 294 + /* No variable brightness for blinking LEDs */ 342 295 goto out; 343 - ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK1); 344 - break; 296 + } 297 + } else { 298 + switch (value) { 299 + case LED_FULL: 300 + ls = pca955x_ledsel(ls, bit, PCA955X_LS_LED_ON); 301 + break; 302 + case LED_OFF: 303 + ls = pca955x_ledsel(ls, bit, PCA955X_LS_LED_OFF); 304 + break; 305 + default: 306 + /* 307 + * Use PWM1 for all other values. This has the unwanted 308 + * side effect of making all LEDs on the chip share the 309 + * same brightness level if set to a value other than 310 + * OFF or FULL. But, this is probably better than just 311 + * turning off for all other values. 312 + */ 313 + ret = pca955x_write_pwm(pca955x, 1, 255 - value); 314 + if (ret) 315 + goto out; 316 + ls = pca955x_ledsel(ls, bit, PCA955X_LS_BLINK1); 317 + break; 318 + } 345 319 } 346 320 347 - ret = pca955x_write_ls(pca955x->client, chip_ls, ls); 321 + ret = pca955x_write_ls(pca955x, reg, ls); 322 + 323 + out: 324 + mutex_unlock(&pca955x->lock); 325 + 326 + return ret; 327 + } 328 + 329 + static u8 pca955x_period_to_psc(struct pca955x *pca955x, unsigned long period) 330 + { 331 + /* psc register value = (blink period * coeff) - 1 */ 332 + period *= pca955x->chipdef->blink_div; 333 + period /= MSEC_PER_SEC; 334 + period -= 1; 335 + 336 + return period; 337 + } 338 + 339 + static unsigned long pca955x_psc_to_period(struct pca955x *pca955x, u8 psc) 340 + { 341 + unsigned long period = psc; 342 + 343 + /* blink period = (psc register value + 1) / coeff */ 344 + period += 1; 345 + period *= MSEC_PER_SEC; 346 + period /= pca955x->chipdef->blink_div; 347 + 348 + return period; 349 + } 350 + 351 + static int pca955x_led_blink(struct led_classdev *led_cdev, 352 + unsigned long *delay_on, unsigned long *delay_off) 353 + { 354 + struct pca955x_led *pca955x_led = led_to_pca955x(led_cdev); 355 + struct pca955x *pca955x = pca955x_led->pca955x; 356 + unsigned long period = *delay_on + *delay_off; 357 + int ret = 0; 358 + 359 + mutex_lock(&pca955x->lock); 360 + 361 + if (period) { 362 + if (*delay_on != *delay_off) { 363 + ret = -EINVAL; 364 + goto out; 365 + } 366 + 367 + if (period < pca955x_psc_to_period(pca955x, 0) || 368 + period > pca955x_psc_to_period(pca955x, 0xff)) { 369 + ret = -EINVAL; 370 + goto out; 371 + } 372 + } else { 373 + period = pca955x->active_blink ? pca955x->blink_period : 374 + PCA955X_BLINK_DEFAULT_MS; 375 + } 376 + 377 + if (!pca955x->active_blink || 378 + pca955x->active_blink == BIT(pca955x_led->led_num) || 379 + pca955x->blink_period == period) { 380 + u8 psc = pca955x_period_to_psc(pca955x, period); 381 + 382 + if (!test_and_set_bit(pca955x_led->led_num, 383 + &pca955x->active_blink)) { 384 + u8 ls; 385 + int reg = pca955x_led->led_num / 4; 386 + int bit = pca955x_led->led_num % 4; 387 + 388 + ret = pca955x_read_ls(pca955x, reg, &ls); 389 + if (ret) 390 + goto out; 391 + 392 + ls = pca955x_ledsel(ls, bit, PCA955X_LS_BLINK0); 393 + ret = pca955x_write_ls(pca955x, reg, ls); 394 + if (ret) 395 + goto out; 396 + 397 + /* 398 + * Force 50% duty cycle to maintain the specified 399 + * blink rate. 400 + */ 401 + ret = pca955x_write_pwm(pca955x, 0, 128); 402 + if (ret) 403 + goto out; 404 + } 405 + 406 + if (pca955x->blink_period != period) { 407 + pca955x->blink_period = period; 408 + ret = pca955x_write_psc(pca955x, 0, psc); 409 + if (ret) 410 + goto out; 411 + } 412 + 413 + period = pca955x_psc_to_period(pca955x, psc); 414 + period /= 2; 415 + *delay_on = period; 416 + *delay_off = period; 417 + } else { 418 + ret = -EBUSY; 419 + } 348 420 349 421 out: 350 422 mutex_unlock(&pca955x->lock); ··· 581 455 struct led_classdev *led; 582 456 struct led_init_data init_data; 583 457 struct i2c_adapter *adapter; 584 - int i, err; 458 + int i, bit, err, nls, reg; 459 + u8 ls1[4]; 460 + u8 ls2[4]; 585 461 struct pca955x_platform_data *pdata; 462 + u8 psc0; 463 + bool keep_psc0 = false; 586 464 bool set_default_label = false; 587 - bool keep_pwm = false; 588 465 char default_label[8]; 589 466 590 467 chip = i2c_get_match_data(client); ··· 638 509 mutex_init(&pca955x->lock); 639 510 pca955x->client = client; 640 511 pca955x->chipdef = chip; 512 + pca955x->blink_period = PCA955X_BLINK_DEFAULT_MS; 641 513 642 514 init_data.devname_mandatory = false; 643 515 init_data.devicename = "pca955x"; 516 + 517 + nls = pca955x_num_led_regs(chip->bits); 518 + /* Use auto-increment feature to read all the LED selectors at once. */ 519 + err = i2c_smbus_read_i2c_block_data(client, 520 + 0x10 | (pca955x_num_input_regs(chip->bits) + 4), nls, 521 + ls1); 522 + if (err < 0) 523 + return err; 524 + 525 + for (i = 0; i < nls; i++) 526 + ls2[i] = ls1[i]; 644 527 645 528 for (i = 0; i < chip->bits; i++) { 646 529 pca955x_led = &pca955x->leds[i]; ··· 665 524 case PCA955X_TYPE_GPIO: 666 525 break; 667 526 case PCA955X_TYPE_LED: 527 + bit = i % 4; 528 + reg = i / 4; 668 529 led = &pca955x_led->led_cdev; 669 530 led->brightness_set_blocking = pca955x_led_set; 670 531 led->brightness_get = pca955x_led_get; 532 + led->blink_set = pca955x_led_blink; 671 533 672 - if (pdata->leds[i].default_state == LEDS_DEFSTATE_OFF) { 673 - err = pca955x_led_set(led, LED_OFF); 674 - if (err) 675 - return err; 676 - } else if (pdata->leds[i].default_state == LEDS_DEFSTATE_ON) { 677 - err = pca955x_led_set(led, LED_FULL); 678 - if (err) 679 - return err; 534 + if (pdata->leds[i].default_state == LEDS_DEFSTATE_OFF) 535 + ls2[reg] = pca955x_ledsel(ls2[reg], bit, PCA955X_LS_LED_OFF); 536 + else if (pdata->leds[i].default_state == LEDS_DEFSTATE_ON) 537 + ls2[reg] = pca955x_ledsel(ls2[reg], bit, PCA955X_LS_LED_ON); 538 + else if (pca955x_ledstate(ls2[reg], bit) == PCA955X_LS_BLINK0) { 539 + keep_psc0 = true; 540 + set_bit(i, &pca955x->active_blink); 680 541 } 681 542 682 543 init_data.fwnode = pdata->leds[i].fwnode; ··· 707 564 return err; 708 565 709 566 set_bit(i, &pca955x->active_pins); 710 - 711 - /* 712 - * For default-state == "keep", let the core update the 713 - * brightness from the hardware, then check the 714 - * brightness to see if it's using PWM1. If so, PWM1 715 - * should not be written below. 716 - */ 717 - if (pdata->leds[i].default_state == LEDS_DEFSTATE_KEEP) { 718 - if (led->brightness != LED_FULL && 719 - led->brightness != LED_OFF && 720 - led->brightness != LED_HALF) 721 - keep_pwm = true; 722 - } 723 567 } 724 568 } 725 569 726 - /* PWM0 is used for half brightness or 50% duty cycle */ 727 - err = pca955x_write_pwm(client, 0, 255 - LED_HALF); 728 - if (err) 729 - return err; 730 - 731 - if (!keep_pwm) { 732 - /* PWM1 is used for variable brightness, default to OFF */ 733 - err = pca955x_write_pwm(client, 1, 0); 734 - if (err) 735 - return err; 570 + for (i = 0; i < nls; i++) { 571 + if (ls1[i] != ls2[i]) { 572 + err = pca955x_write_ls(pca955x, i, ls2[i]); 573 + if (err) 574 + return err; 575 + } 736 576 } 737 577 738 - /* Set to fast frequency so we do not see flashing */ 739 - err = pca955x_write_psc(client, 0, 0); 578 + if (keep_psc0) { 579 + err = pca955x_read_psc(pca955x, 0, &psc0); 580 + } else { 581 + psc0 = pca955x_period_to_psc(pca955x, pca955x->blink_period); 582 + err = pca955x_write_psc(pca955x, 0, psc0); 583 + } 584 + 740 585 if (err) 741 586 return err; 742 - err = pca955x_write_psc(client, 1, 0); 587 + 588 + pca955x->blink_period = pca955x_psc_to_period(pca955x, psc0); 589 + 590 + /* Set PWM1 to fast frequency so we do not see flashing */ 591 + err = pca955x_write_psc(pca955x, 1, 0); 743 592 if (err) 744 593 return err; 745 594
+11 -10
drivers/leds/leds-st1202.c
··· 99 99 value_h = (u8)(value >> 8); 100 100 101 101 /* 102 - * Datasheet: Register address low = 1Eh + 2*(xh) + 18h*(yh), 103 - * where x is the channel number (led number) in hexadecimal (x = 00h .. 0Bh) 104 - * and y is the pattern number in hexadecimal (y = 00h .. 07h) 102 + * Datasheet: Register address low = 1Eh + 2*(xh) + 18h*(yh), 103 + * where x is the channel number (led number) in hexadecimal (x = 00h .. 0Bh) 104 + * and y is the pattern number in hexadecimal (y = 00h .. 07h) 105 105 */ 106 106 ret = st1202_write_reg(chip, (ST1202_PATTERN_PWM + (led_num * 2) + 0x18 * pattern), 107 107 value_l); ··· 189 189 static int st1202_led_set(struct led_classdev *ldev, enum led_brightness value) 190 190 { 191 191 struct st1202_led *led = cdev_to_st1202_led(ldev); 192 - struct st1202_chip *chip = led->chip; 193 192 194 - return st1202_channel_set(chip, led->led_num, value == LED_OFF ? false : true); 193 + return st1202_channel_set(led->chip, led->led_num, !!value); 195 194 } 196 195 197 196 static int st1202_led_pattern_clear(struct led_classdev *ldev) ··· 287 288 guard(mutex)(&chip->lock); 288 289 289 290 /* 290 - * Once the supply voltage is applied, the LED1202 executes some internal checks, 291 - * afterwords it stops the oscillator and puts the internal LDO in quiescent mode. 291 + * Once the supply voltage is applied, the LED1202 executes some internal checks. 292 + * Afterwards, it stops the oscillator and puts the internal LDO in quiescent mode. 292 293 * To start the device, EN bit must be set inside the “Device Enable” register at 293 294 * address 01h. As soon as EN is set, the LED1202 loads the adjustment parameters 294 295 * from the internal non-volatile memory and performs an auto-calibration procedure ··· 344 345 if (!chip) 345 346 return -ENOMEM; 346 347 347 - devm_mutex_init(&client->dev, &chip->lock); 348 + ret = devm_mutex_init(&client->dev, &chip->lock); 349 + if (ret < 0) 350 + return ret; 348 351 chip->client = client; 349 352 350 - ret = st1202_dt_init(chip); 353 + ret = st1202_setup(chip); 351 354 if (ret < 0) 352 355 return ret; 353 356 354 - ret = st1202_setup(chip); 357 + ret = st1202_dt_init(chip); 355 358 if (ret < 0) 356 359 return ret; 357 360
+4 -1
drivers/leds/rgb/leds-pwm-multicolor.c
··· 141 141 142 142 /* init the multicolor's LED class device */ 143 143 cdev = &priv->mc_cdev.led_cdev; 144 - fwnode_property_read_u32(mcnode, "max-brightness", 144 + ret = fwnode_property_read_u32(mcnode, "max-brightness", 145 145 &cdev->max_brightness); 146 + if (ret) 147 + goto release_mcnode; 148 + 146 149 cdev->flags = LED_CORE_SUSPENDRESUME; 147 150 cdev->brightness_set_blocking = led_pwm_mc_set; 148 151
+12 -11
drivers/leds/rgb/leds-qcom-lpg.c
··· 24 24 #define LPG_PATTERN_CONFIG_REG 0x40 25 25 #define LPG_SIZE_CLK_REG 0x41 26 26 #define PWM_CLK_SELECT_MASK GENMASK(1, 0) 27 + #define PWM_SIZE_SELECT_MASK BIT(2) 27 28 #define PWM_CLK_SELECT_HI_RES_MASK GENMASK(2, 0) 28 29 #define PWM_SIZE_HI_RES_MASK GENMASK(6, 4) 29 30 #define LPG_PREDIV_CLK_REG 0x42 ··· 413 412 static const unsigned int lpg_clk_rates[] = {0, 1024, 32768, 19200000}; 414 413 static const unsigned int lpg_clk_rates_hi_res[] = {0, 1024, 32768, 19200000, 76800000}; 415 414 static const unsigned int lpg_pre_divs[] = {1, 3, 5, 6}; 416 - static const unsigned int lpg_pwm_resolution[] = {9}; 417 - static const unsigned int lpg_pwm_resolution_hi_res[] = {8, 9, 10, 11, 12, 13, 14, 15}; 415 + static const unsigned int lpg_pwm_resolution[] = {6, 9}; 416 + static const unsigned int lpg_pwm_resolution_hi_res[] = {8, 9, 10, 11, 12, 13, 14, 15}; 418 417 419 418 static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period) 420 419 { ··· 437 436 * period = -------------------------- 438 437 * refclk 439 438 * 440 - * Resolution = 2^9 bits for PWM or 439 + * Resolution = 2^{6 or 9} bits for PWM or 441 440 * 2^{8, 9, 10, 11, 12, 13, 14, 15} bits for high resolution PWM 442 441 * pre_div = {1, 3, 5, 6} and 443 442 * M = [0..7]. 444 443 * 445 - * This allows for periods between 27uS and 384s for PWM channels and periods between 444 + * This allows for periods between 3uS and 384s for PWM channels and periods between 446 445 * 3uS and 24576s for high resolution PWMs. 447 446 * The PWM framework wants a period of equal or lower length than requested, 448 447 * reject anything below minimum period. ··· 462 461 max_res = LPG_RESOLUTION_9BIT; 463 462 } 464 463 465 - min_period = div64_u64((u64)NSEC_PER_SEC * (1 << pwm_resolution_arr[0]), 464 + min_period = div64_u64((u64)NSEC_PER_SEC * ((1 << pwm_resolution_arr[0]) - 1), 466 465 clk_rate_arr[clk_len - 1]); 467 466 if (period <= min_period) 468 467 return -EINVAL; ··· 483 482 */ 484 483 485 484 for (i = 0; i < pwm_resolution_count; i++) { 486 - resolution = 1 << pwm_resolution_arr[i]; 485 + resolution = (1 << pwm_resolution_arr[i]) - 1; 487 486 for (clk_sel = 1; clk_sel < clk_len; clk_sel++) { 488 487 u64 numerator = period * clk_rate_arr[clk_sel]; 489 488 ··· 530 529 unsigned int clk_rate; 531 530 532 531 if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { 533 - max = LPG_RESOLUTION_15BIT - 1; 532 + max = BIT(lpg_pwm_resolution_hi_res[chan->pwm_resolution_sel]) - 1; 534 533 clk_rate = lpg_clk_rates_hi_res[chan->clk_sel]; 535 534 } else { 536 - max = LPG_RESOLUTION_9BIT - 1; 535 + max = BIT(lpg_pwm_resolution[chan->pwm_resolution_sel]) - 1; 537 536 clk_rate = lpg_clk_rates[chan->clk_sel]; 538 537 } 539 538 ··· 559 558 val |= GENMASK(5, 4); 560 559 break; 561 560 case LPG_SUBTYPE_PWM: 562 - val |= BIT(2); 561 + val |= FIELD_PREP(PWM_SIZE_SELECT_MASK, chan->pwm_resolution_sel); 563 562 break; 564 563 case LPG_SUBTYPE_HI_RES_PWM: 565 564 val |= FIELD_PREP(PWM_SIZE_HI_RES_MASK, chan->pwm_resolution_sel); ··· 1277 1276 resolution = lpg_pwm_resolution_hi_res[FIELD_GET(PWM_SIZE_HI_RES_MASK, val)]; 1278 1277 } else { 1279 1278 refclk = lpg_clk_rates[FIELD_GET(PWM_CLK_SELECT_MASK, val)]; 1280 - resolution = 9; 1279 + resolution = lpg_pwm_resolution[FIELD_GET(PWM_SIZE_SELECT_MASK, val)]; 1281 1280 } 1282 1281 1283 1282 if (refclk) { ··· 1292 1291 if (ret) 1293 1292 return ret; 1294 1293 1295 - state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * (1 << resolution) * 1294 + state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * ((1 << resolution) - 1) * 1296 1295 pre_div * (1 << m), refclk); 1297 1296 state->duty_cycle = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * pwm_value * pre_div * (1 << m), refclk); 1298 1297 } else {
drivers/leds/simple/Kconfig drivers/leds/simatic/Kconfig
drivers/leds/simple/Makefile drivers/leds/simatic/Makefile
drivers/leds/simple/simatic-ipc-leds-gpio-apollolake.c drivers/leds/simatic/simatic-ipc-leds-gpio-apollolake.c
drivers/leds/simple/simatic-ipc-leds-gpio-core.c drivers/leds/simatic/simatic-ipc-leds-gpio-core.c
drivers/leds/simple/simatic-ipc-leds-gpio-elkhartlake.c drivers/leds/simatic/simatic-ipc-leds-gpio-elkhartlake.c
drivers/leds/simple/simatic-ipc-leds-gpio-f7188x.c drivers/leds/simatic/simatic-ipc-leds-gpio-f7188x.c
drivers/leds/simple/simatic-ipc-leds-gpio.h drivers/leds/simatic/simatic-ipc-leds-gpio.h
drivers/leds/simple/simatic-ipc-leds.c drivers/leds/simatic/simatic-ipc-leds.c
+13 -3
drivers/leds/trigger/ledtrig-netdev.c
··· 68 68 unsigned int last_activity; 69 69 70 70 unsigned long mode; 71 + unsigned long blink_delay; 71 72 int link_speed; 72 73 __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_link_modes); 73 74 u8 duplex; ··· 87 86 /* Already validated, hw control is possible with the requested mode */ 88 87 if (trigger_data->hw_control) { 89 88 led_cdev->hw_control_set(led_cdev, trigger_data->mode); 89 + if (led_cdev->blink_set) { 90 + led_cdev->blink_set(led_cdev, &trigger_data->blink_delay, 91 + &trigger_data->blink_delay); 92 + } 90 93 91 94 return; 92 95 } ··· 459 454 size_t size) 460 455 { 461 456 struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); 457 + struct led_classdev *led_cdev = trigger_data->led_cdev; 462 458 unsigned long value; 463 459 int ret; 464 460 465 - if (trigger_data->hw_control) 461 + if (trigger_data->hw_control && !led_cdev->blink_set) 466 462 return -EINVAL; 467 463 468 464 ret = kstrtoul(buf, 0, &value); ··· 472 466 473 467 /* impose some basic bounds on the timer interval */ 474 468 if (value >= 5 && value <= 10000) { 475 - cancel_delayed_work_sync(&trigger_data->work); 469 + if (trigger_data->hw_control) { 470 + trigger_data->blink_delay = value; 471 + } else { 472 + cancel_delayed_work_sync(&trigger_data->work); 476 473 477 - atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); 474 + atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); 475 + } 478 476 set_baseline_state(trigger_data); /* resets timer */ 479 477 } 480 478