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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'leds-5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds

Pull LED updates from Pavel Machek:
"A new driver for bcm63138, is31fl319x updates, fixups for multicolor.

The clevo-mail driver got disabled, it needs an API fix"

* tag 'leds-5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/pavel/linux-leds: (23 commits)
leds: is31fl319x: use simple i2c probe function
leds: is31fl319x: Fix devm vs. non-devm ordering
leds: is31fl319x: Make use of dev_err_probe()
leds: is31fl319x: Make use of device properties
leds: is31fl319x: Cleanup formatting and dev_dbg calls
leds: is31fl319x: Add support for is31fl319{0,1,3} chips
leds: is31fl319x: Move chipset-specific values in chipdef struct
leds: is31fl319x: Use non-wildcard names for vars, structs and defines
leds: is31fl319x: Add missing si-en compatibles
dt-bindings: leds: pwm-multicolor: document max-brigthness
leds: turris-omnia: convert to use dev_groups
leds: leds-bcm63138: get rid of LED_OFF
leds: add help info about BCM63138 module name
dt-bindings: leds: leds-bcm63138: unify full stops in descriptions
dt-bindings: leds: lp50xx: fix LED children names
dt-bindings: leds: class-multicolor: reference class directly in multi-led node
leds: bcm63138: add support for BCM63138 controller
dt-bindings: leds: add Broadcom's BCM63138 controller
leds: clevo-mail: Mark as broken pending interface fix
leds: pwm-multicolor: Support active-low LEDs
...

+811 -218
+2
Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml
··· 33 33 "^multi-led@[0-9a-b]$": 34 34 type: object 35 35 $ref: leds-class-multicolor.yaml# 36 + unevaluatedProperties: false 37 + 36 38 description: 37 39 This node represents one of the RGB LED devices on Turris Omnia. 38 40 No subnodes need to be added for subchannels since this controller only
+95
Documentation/devicetree/bindings/leds/leds-bcm63138.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/leds-bcm63138.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Broadcom's BCM63138 LEDs controller 8 + 9 + maintainers: 10 + - Rafał Miłecki <rafal@milecki.pl> 11 + 12 + description: | 13 + This LEDs controller was first used on BCM63138 and later reused on BCM4908, 14 + BCM6848, BCM6858, BCM63138, BCM63148, BCM63381 and BCM68360 SoCs. 15 + 16 + It supports up to 32 LEDs that can be connected parallelly or serially. It 17 + also includes limited support for hardware blinking. 18 + 19 + Binding serially connected LEDs isn't documented yet. 20 + 21 + properties: 22 + compatible: 23 + oneOf: 24 + - items: 25 + - enum: 26 + - brcm,bcm4908-leds 27 + - brcm,bcm6848-leds 28 + - brcm,bcm6858-leds 29 + - brcm,bcm63148-leds 30 + - brcm,bcm63381-leds 31 + - brcm,bcm68360-leds 32 + - const: brcm,bcm63138-leds 33 + - const: brcm,bcm63138-leds 34 + 35 + reg: 36 + maxItems: 1 37 + 38 + "#address-cells": 39 + const: 1 40 + 41 + "#size-cells": 42 + const: 0 43 + 44 + patternProperties: 45 + "^led@[a-f0-9]+$": 46 + type: object 47 + 48 + $ref: common.yaml# 49 + 50 + properties: 51 + reg: 52 + maxItems: 1 53 + description: LED pin number 54 + 55 + active-low: 56 + type: boolean 57 + description: Makes LED active low 58 + 59 + required: 60 + - reg 61 + 62 + unevaluatedProperties: false 63 + 64 + required: 65 + - reg 66 + - "#address-cells" 67 + - "#size-cells" 68 + 69 + additionalProperties: false 70 + 71 + examples: 72 + - | 73 + #include <dt-bindings/leds/common.h> 74 + 75 + leds@ff800800 { 76 + compatible = "brcm,bcm4908-leds", "brcm,bcm63138-leds"; 77 + reg = <0xff800800 0xdc>; 78 + 79 + #address-cells = <1>; 80 + #size-cells = <0>; 81 + 82 + led@0 { 83 + reg = <0x0>; 84 + function = LED_FUNCTION_POWER; 85 + color = <LED_COLOR_ID_GREEN>; 86 + default-state = "on"; 87 + }; 88 + 89 + led@3 { 90 + reg = <0x3>; 91 + function = LED_FUNCTION_STATUS; 92 + color = <LED_COLOR_ID_GREEN>; 93 + active-low; 94 + }; 95 + };
+14 -14
Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml
··· 19 19 LED class. Common LED nodes and properties are inherited from the common.yaml 20 20 within this documentation directory. 21 21 22 - patternProperties: 23 - "^multi-led(@[0-9a-f])?$": 24 - type: object 25 - description: Represents the LEDs that are to be grouped. 26 - properties: 27 - color: 28 - description: | 29 - For multicolor LED support this property should be defined as either 30 - LED_COLOR_ID_RGB or LED_COLOR_ID_MULTI which can be found in 31 - include/linux/leds/common.h. 32 - enum: [ 8, 9 ] 22 + properties: 23 + $nodename: 24 + pattern: "^multi-led(@[0-9a-f])?$" 33 25 34 - $ref: "common.yaml#" 26 + color: 27 + description: | 28 + For multicolor LED support this property should be defined as either 29 + LED_COLOR_ID_RGB or LED_COLOR_ID_MULTI which can be found in 30 + include/linux/leds/common.h. 31 + enum: [ 8, 9 ] 35 32 36 - required: 37 - - color 33 + required: 34 + - color 35 + 36 + allOf: 37 + - $ref: "common.yaml#" 38 38 39 39 additionalProperties: true 40 40
+9 -1
Documentation/devicetree/bindings/leds/leds-lp50xx.yaml
··· 56 56 '^multi-led@[0-9a-f]$': 57 57 type: object 58 58 $ref: leds-class-multicolor.yaml# 59 + unevaluatedProperties: false 60 + 59 61 properties: 60 62 reg: 61 63 minItems: 1 ··· 67 65 for the child node. The LED modules can either be used stand alone 68 66 or grouped into a module bank. 69 67 68 + '#address-cells': 69 + const: 1 70 + 71 + '#size-cells': 72 + const: 0 73 + 70 74 patternProperties: 71 - "(^led-[0-9a-f]$|led)": 75 + "^led@[0-9a-f]+$": 72 76 type: object 73 77 $ref: common.yaml# 74 78
+12 -3
Documentation/devicetree/bindings/leds/leds-pwm-multicolor.yaml
··· 19 19 20 20 multi-led: 21 21 type: object 22 + $ref: leds-class-multicolor.yaml# 23 + unevaluatedProperties: false 24 + 25 + properties: 26 + max-brightness: 27 + description: 28 + Maximum brightness possible for the LED 29 + $ref: /schemas/types.yaml#/definitions/uint32 22 30 23 31 patternProperties: 24 32 "^led-[0-9a-z]+$": ··· 41 33 42 34 pwm-names: true 43 35 36 + active-low: 37 + description: For PWMs where the LED is wired to supply rather than ground. 38 + type: boolean 39 + 44 40 color: true 45 41 46 42 required: ··· 53 41 54 42 required: 55 43 - compatible 56 - 57 - allOf: 58 - - $ref: leds-class-multicolor.yaml# 59 44 60 45 additionalProperties: false 61 46
+2
Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
··· 59 59 multi-led: 60 60 type: object 61 61 $ref: leds-class-multicolor.yaml# 62 + unevaluatedProperties: false 63 + 62 64 properties: 63 65 "#address-cells": 64 66 const: 1
+5 -5
drivers/leds/Kconfig
··· 447 447 448 448 config LEDS_CLEVO_MAIL 449 449 tristate "Mail LED on Clevo notebook" 450 - depends on LEDS_CLASS 450 + depends on LEDS_CLASS && BROKEN 451 451 depends on X86 && SERIO_I8042 && DMI 452 452 help 453 453 This driver makes the mail LED accessible from userspace 454 - programs through the leds subsystem. This LED have three 455 - known mode: off, blink at 0.5Hz and blink at 1Hz. 454 + programs through the LEDs subsystem. This LED has three 455 + known modes: off, blink at 0.5Hz and blink at 1Hz. 456 456 457 457 The driver supports two kinds of interface: using ledtrig-timer 458 458 or through /sys/class/leds/clevo::mail/brightness. As this LED 459 - cannot change it's brightness it blinks instead. The brightness 459 + cannot change its brightness it blinks instead. The brightness 460 460 value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means 461 461 blink at 1Hz. 462 462 ··· 697 697 698 698 config LEDS_IS31FL319X 699 699 tristate "LED Support for ISSI IS31FL319x I2C LED controller family" 700 - depends on LEDS_CLASS && I2C && OF 700 + depends on LEDS_CLASS && I2C 701 701 select REGMAP_I2C 702 702 help 703 703 This option enables support for LEDs connected to ISSI IS31FL319x
+14
drivers/leds/blink/Kconfig
··· 1 + config LEDS_BCM63138 2 + tristate "LED Support for Broadcom BCM63138 SoC" 3 + depends on LEDS_CLASS 4 + depends on ARCH_BCM4908 || ARCH_BCM_5301X || BCM63XX || COMPILE_TEST 5 + depends on HAS_IOMEM 6 + depends on OF 7 + default ARCH_BCM4908 8 + help 9 + This option enables support for LED controller that is part of 10 + BCM63138 SoC. The same hardware block is known to be also used 11 + in BCM4908, BCM6848, BCM6858, BCM63148, BCM63381 and BCM68360. 12 + 13 + If compiled as module it will be called leds-bcm63138. 14 + 1 15 config LEDS_LGM 2 16 tristate "LED support for LGM SoC series" 3 17 depends on X86 || COMPILE_TEST
+1
drivers/leds/blink/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 + obj-$(CONFIG_LEDS_BCM63138) += leds-bcm63138.o 2 3 obj-$(CONFIG_LEDS_LGM) += leds-lgm-sso.o
+307
drivers/leds/blink/leds-bcm63138.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> 4 + */ 5 + #include <linux/delay.h> 6 + #include <linux/io.h> 7 + #include <linux/leds.h> 8 + #include <linux/module.h> 9 + #include <linux/of.h> 10 + #include <linux/pinctrl/consumer.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/spinlock.h> 13 + 14 + #define BCM63138_MAX_LEDS 32 15 + #define BCM63138_MAX_BRIGHTNESS 9 16 + 17 + #define BCM63138_LED_BITS 4 /* how many bits control a single LED */ 18 + #define BCM63138_LED_MASK ((1 << BCM63138_LED_BITS) - 1) /* 0xf */ 19 + #define BCM63138_LEDS_PER_REG (32 / BCM63138_LED_BITS) /* 8 */ 20 + 21 + #define BCM63138_GLB_CTRL 0x00 22 + #define BCM63138_GLB_CTRL_SERIAL_LED_DATA_PPOL 0x00000002 23 + #define BCM63138_GLB_CTRL_SERIAL_LED_EN_POL 0x00000008 24 + #define BCM63138_MASK 0x04 25 + #define BCM63138_HW_LED_EN 0x08 26 + #define BCM63138_SERIAL_LED_SHIFT_SEL 0x0c 27 + #define BCM63138_FLASH_RATE_CTRL1 0x10 28 + #define BCM63138_FLASH_RATE_CTRL2 0x14 29 + #define BCM63138_FLASH_RATE_CTRL3 0x18 30 + #define BCM63138_FLASH_RATE_CTRL4 0x1c 31 + #define BCM63138_BRIGHT_CTRL1 0x20 32 + #define BCM63138_BRIGHT_CTRL2 0x24 33 + #define BCM63138_BRIGHT_CTRL3 0x28 34 + #define BCM63138_BRIGHT_CTRL4 0x2c 35 + #define BCM63138_POWER_LED_CFG 0x30 36 + #define BCM63138_HW_POLARITY 0xb4 37 + #define BCM63138_SW_DATA 0xb8 38 + #define BCM63138_SW_POLARITY 0xbc 39 + #define BCM63138_PARALLEL_LED_POLARITY 0xc0 40 + #define BCM63138_SERIAL_LED_POLARITY 0xc4 41 + #define BCM63138_HW_LED_STATUS 0xc8 42 + #define BCM63138_FLASH_CTRL_STATUS 0xcc 43 + #define BCM63138_FLASH_BRT_CTRL 0xd0 44 + #define BCM63138_FLASH_P_LED_OUT_STATUS 0xd4 45 + #define BCM63138_FLASH_S_LED_OUT_STATUS 0xd8 46 + 47 + struct bcm63138_leds { 48 + struct device *dev; 49 + void __iomem *base; 50 + spinlock_t lock; 51 + }; 52 + 53 + struct bcm63138_led { 54 + struct bcm63138_leds *leds; 55 + struct led_classdev cdev; 56 + u32 pin; 57 + bool active_low; 58 + }; 59 + 60 + /* 61 + * I/O access 62 + */ 63 + 64 + static void bcm63138_leds_write(struct bcm63138_leds *leds, unsigned int reg, 65 + u32 data) 66 + { 67 + writel(data, leds->base + reg); 68 + } 69 + 70 + static unsigned long bcm63138_leds_read(struct bcm63138_leds *leds, 71 + unsigned int reg) 72 + { 73 + return readl(leds->base + reg); 74 + } 75 + 76 + static void bcm63138_leds_update_bits(struct bcm63138_leds *leds, 77 + unsigned int reg, u32 mask, u32 val) 78 + { 79 + WARN_ON(val & ~mask); 80 + 81 + bcm63138_leds_write(leds, reg, (bcm63138_leds_read(leds, reg) & ~mask) | (val & mask)); 82 + } 83 + 84 + /* 85 + * Helpers 86 + */ 87 + 88 + static void bcm63138_leds_set_flash_rate(struct bcm63138_leds *leds, 89 + struct bcm63138_led *led, 90 + u8 value) 91 + { 92 + int reg_offset = (led->pin >> fls((BCM63138_LEDS_PER_REG - 1))) * 4; 93 + int shift = (led->pin & (BCM63138_LEDS_PER_REG - 1)) * BCM63138_LED_BITS; 94 + 95 + bcm63138_leds_update_bits(leds, BCM63138_FLASH_RATE_CTRL1 + reg_offset, 96 + BCM63138_LED_MASK << shift, value << shift); 97 + } 98 + 99 + static void bcm63138_leds_set_bright(struct bcm63138_leds *leds, 100 + struct bcm63138_led *led, 101 + u8 value) 102 + { 103 + int reg_offset = (led->pin >> fls((BCM63138_LEDS_PER_REG - 1))) * 4; 104 + int shift = (led->pin & (BCM63138_LEDS_PER_REG - 1)) * BCM63138_LED_BITS; 105 + 106 + bcm63138_leds_update_bits(leds, BCM63138_BRIGHT_CTRL1 + reg_offset, 107 + BCM63138_LED_MASK << shift, value << shift); 108 + } 109 + 110 + static void bcm63138_leds_enable_led(struct bcm63138_leds *leds, 111 + struct bcm63138_led *led, 112 + enum led_brightness value) 113 + { 114 + u32 bit = BIT(led->pin); 115 + 116 + bcm63138_leds_update_bits(leds, BCM63138_SW_DATA, bit, value ? bit : 0); 117 + } 118 + 119 + /* 120 + * API callbacks 121 + */ 122 + 123 + static void bcm63138_leds_brightness_set(struct led_classdev *led_cdev, 124 + enum led_brightness value) 125 + { 126 + struct bcm63138_led *led = container_of(led_cdev, struct bcm63138_led, cdev); 127 + struct bcm63138_leds *leds = led->leds; 128 + unsigned long flags; 129 + 130 + spin_lock_irqsave(&leds->lock, flags); 131 + 132 + bcm63138_leds_enable_led(leds, led, value); 133 + if (!value) 134 + bcm63138_leds_set_flash_rate(leds, led, 0); 135 + else 136 + bcm63138_leds_set_bright(leds, led, value); 137 + 138 + spin_unlock_irqrestore(&leds->lock, flags); 139 + } 140 + 141 + static int bcm63138_leds_blink_set(struct led_classdev *led_cdev, 142 + unsigned long *delay_on, 143 + unsigned long *delay_off) 144 + { 145 + struct bcm63138_led *led = container_of(led_cdev, struct bcm63138_led, cdev); 146 + struct bcm63138_leds *leds = led->leds; 147 + unsigned long flags; 148 + u8 value; 149 + 150 + if (!*delay_on && !*delay_off) { 151 + *delay_on = 640; 152 + *delay_off = 640; 153 + } 154 + 155 + if (*delay_on != *delay_off) { 156 + dev_dbg(led_cdev->dev, "Blinking at unequal delays is not supported\n"); 157 + return -EINVAL; 158 + } 159 + 160 + switch (*delay_on) { 161 + case 1152 ... 1408: /* 1280 ms ± 10% */ 162 + value = 0x7; 163 + break; 164 + case 576 ... 704: /* 640 ms ± 10% */ 165 + value = 0x6; 166 + break; 167 + case 288 ... 352: /* 320 ms ± 10% */ 168 + value = 0x5; 169 + break; 170 + case 126 ... 154: /* 140 ms ± 10% */ 171 + value = 0x4; 172 + break; 173 + case 59 ... 72: /* 65 ms ± 10% */ 174 + value = 0x3; 175 + break; 176 + default: 177 + dev_dbg(led_cdev->dev, "Blinking delay value %lu is unsupported\n", 178 + *delay_on); 179 + return -EINVAL; 180 + } 181 + 182 + spin_lock_irqsave(&leds->lock, flags); 183 + 184 + bcm63138_leds_enable_led(leds, led, BCM63138_MAX_BRIGHTNESS); 185 + bcm63138_leds_set_flash_rate(leds, led, value); 186 + 187 + spin_unlock_irqrestore(&leds->lock, flags); 188 + 189 + return 0; 190 + } 191 + 192 + /* 193 + * LED driver 194 + */ 195 + 196 + static void bcm63138_leds_create_led(struct bcm63138_leds *leds, 197 + struct device_node *np) 198 + { 199 + struct led_init_data init_data = { 200 + .fwnode = of_fwnode_handle(np), 201 + }; 202 + struct device *dev = leds->dev; 203 + struct bcm63138_led *led; 204 + struct pinctrl *pinctrl; 205 + u32 bit; 206 + int err; 207 + 208 + led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); 209 + if (!led) { 210 + dev_err(dev, "Failed to alloc LED\n"); 211 + return; 212 + } 213 + 214 + led->leds = leds; 215 + 216 + if (of_property_read_u32(np, "reg", &led->pin)) { 217 + dev_err(dev, "Missing \"reg\" property in %pOF\n", np); 218 + goto err_free; 219 + } 220 + 221 + if (led->pin >= BCM63138_MAX_LEDS) { 222 + dev_err(dev, "Invalid \"reg\" value %d\n", led->pin); 223 + goto err_free; 224 + } 225 + 226 + led->active_low = of_property_read_bool(np, "active-low"); 227 + 228 + led->cdev.max_brightness = BCM63138_MAX_BRIGHTNESS; 229 + led->cdev.brightness_set = bcm63138_leds_brightness_set; 230 + led->cdev.blink_set = bcm63138_leds_blink_set; 231 + 232 + err = devm_led_classdev_register_ext(dev, &led->cdev, &init_data); 233 + if (err) { 234 + dev_err(dev, "Failed to register LED %pOF: %d\n", np, err); 235 + goto err_free; 236 + } 237 + 238 + pinctrl = devm_pinctrl_get_select_default(led->cdev.dev); 239 + if (IS_ERR(pinctrl) && PTR_ERR(pinctrl) != -ENODEV) { 240 + dev_warn(led->cdev.dev, "Failed to select %pOF pinctrl: %ld\n", 241 + np, PTR_ERR(pinctrl)); 242 + } 243 + 244 + bit = BIT(led->pin); 245 + bcm63138_leds_update_bits(leds, BCM63138_PARALLEL_LED_POLARITY, bit, 246 + led->active_low ? 0 : bit); 247 + bcm63138_leds_update_bits(leds, BCM63138_HW_LED_EN, bit, 0); 248 + bcm63138_leds_set_flash_rate(leds, led, 0); 249 + bcm63138_leds_enable_led(leds, led, led->cdev.brightness); 250 + 251 + return; 252 + 253 + err_free: 254 + devm_kfree(dev, led); 255 + } 256 + 257 + static int bcm63138_leds_probe(struct platform_device *pdev) 258 + { 259 + struct device_node *np = dev_of_node(&pdev->dev); 260 + struct device *dev = &pdev->dev; 261 + struct bcm63138_leds *leds; 262 + struct device_node *child; 263 + 264 + leds = devm_kzalloc(dev, sizeof(*leds), GFP_KERNEL); 265 + if (!leds) 266 + return -ENOMEM; 267 + 268 + leds->dev = dev; 269 + 270 + leds->base = devm_platform_ioremap_resource(pdev, 0); 271 + if (IS_ERR(leds->base)) 272 + return PTR_ERR(leds->base); 273 + 274 + spin_lock_init(&leds->lock); 275 + 276 + bcm63138_leds_write(leds, BCM63138_GLB_CTRL, 277 + BCM63138_GLB_CTRL_SERIAL_LED_DATA_PPOL | 278 + BCM63138_GLB_CTRL_SERIAL_LED_EN_POL); 279 + bcm63138_leds_write(leds, BCM63138_HW_LED_EN, 0); 280 + bcm63138_leds_write(leds, BCM63138_SERIAL_LED_POLARITY, 0); 281 + bcm63138_leds_write(leds, BCM63138_PARALLEL_LED_POLARITY, 0); 282 + 283 + for_each_available_child_of_node(np, child) { 284 + bcm63138_leds_create_led(leds, child); 285 + } 286 + 287 + return 0; 288 + } 289 + 290 + static const struct of_device_id bcm63138_leds_of_match_table[] = { 291 + { .compatible = "brcm,bcm63138-leds", }, 292 + { }, 293 + }; 294 + 295 + static struct platform_driver bcm63138_leds_driver = { 296 + .probe = bcm63138_leds_probe, 297 + .driver = { 298 + .name = "leds-bcm63xxx", 299 + .of_match_table = bcm63138_leds_of_match_table, 300 + }, 301 + }; 302 + 303 + module_platform_driver(bcm63138_leds_driver); 304 + 305 + MODULE_AUTHOR("Rafał Miłecki"); 306 + MODULE_LICENSE("GPL"); 307 + MODULE_DEVICE_TABLE(of, bcm63138_leds_of_match_table);
+343 -190
drivers/leds/leds-is31fl319x.c
··· 11 11 #include <linux/err.h> 12 12 #include <linux/i2c.h> 13 13 #include <linux/leds.h> 14 + #include <linux/mod_devicetable.h> 14 15 #include <linux/module.h> 15 - #include <linux/of.h> 16 - #include <linux/of_device.h> 16 + #include <linux/property.h> 17 17 #include <linux/regmap.h> 18 18 #include <linux/slab.h> 19 19 #include <linux/delay.h> ··· 21 21 22 22 /* register numbers */ 23 23 #define IS31FL319X_SHUTDOWN 0x00 24 - #define IS31FL319X_CTRL1 0x01 25 - #define IS31FL319X_CTRL2 0x02 26 - #define IS31FL319X_CONFIG1 0x03 27 - #define IS31FL319X_CONFIG2 0x04 28 - #define IS31FL319X_RAMP_MODE 0x05 29 - #define IS31FL319X_BREATH_MASK 0x06 30 - #define IS31FL319X_PWM(channel) (0x07 + channel) 31 - #define IS31FL319X_DATA_UPDATE 0x10 32 - #define IS31FL319X_T0(channel) (0x11 + channel) 33 - #define IS31FL319X_T123_1 0x1a 34 - #define IS31FL319X_T123_2 0x1b 35 - #define IS31FL319X_T123_3 0x1c 36 - #define IS31FL319X_T4(channel) (0x1d + channel) 37 - #define IS31FL319X_TIME_UPDATE 0x26 38 - #define IS31FL319X_RESET 0xff 39 24 40 - #define IS31FL319X_REG_CNT (IS31FL319X_RESET + 1) 25 + /* registers for 3190, 3191 and 3193 */ 26 + #define IS31FL3190_BREATHING 0x01 27 + #define IS31FL3190_LEDMODE 0x02 28 + #define IS31FL3190_CURRENT 0x03 29 + #define IS31FL3190_PWM(channel) (0x04 + channel) 30 + #define IS31FL3190_DATA_UPDATE 0x07 31 + #define IS31FL3190_T0(channel) (0x0a + channel) 32 + #define IS31FL3190_T1T2(channel) (0x10 + channel) 33 + #define IS31FL3190_T3T4(channel) (0x16 + channel) 34 + #define IS31FL3190_TIME_UPDATE 0x1c 35 + #define IS31FL3190_LEDCONTROL 0x1d 36 + #define IS31FL3190_RESET 0x2f 37 + 38 + #define IS31FL3190_CURRENT_uA_MIN 5000 39 + #define IS31FL3190_CURRENT_uA_DEFAULT 42000 40 + #define IS31FL3190_CURRENT_uA_MAX 42000 41 + #define IS31FL3190_CURRENT_MASK GENMASK(4, 2) 42 + #define IS31FL3190_CURRENT_5_mA 0x02 43 + #define IS31FL3190_CURRENT_10_mA 0x01 44 + #define IS31FL3190_CURRENT_17dot5_mA 0x04 45 + #define IS31FL3190_CURRENT_30_mA 0x03 46 + #define IS31FL3190_CURRENT_42_mA 0x00 47 + 48 + /* registers for 3196 and 3199 */ 49 + #define IS31FL3196_CTRL1 0x01 50 + #define IS31FL3196_CTRL2 0x02 51 + #define IS31FL3196_CONFIG1 0x03 52 + #define IS31FL3196_CONFIG2 0x04 53 + #define IS31FL3196_RAMP_MODE 0x05 54 + #define IS31FL3196_BREATH_MARK 0x06 55 + #define IS31FL3196_PWM(channel) (0x07 + channel) 56 + #define IS31FL3196_DATA_UPDATE 0x10 57 + #define IS31FL3196_T0(channel) (0x11 + channel) 58 + #define IS31FL3196_T123_1 0x1a 59 + #define IS31FL3196_T123_2 0x1b 60 + #define IS31FL3196_T123_3 0x1c 61 + #define IS31FL3196_T4(channel) (0x1d + channel) 62 + #define IS31FL3196_TIME_UPDATE 0x26 63 + #define IS31FL3196_RESET 0xff 64 + 65 + #define IS31FL3196_REG_CNT (IS31FL3196_RESET + 1) 41 66 42 67 #define IS31FL319X_MAX_LEDS 9 43 68 44 69 /* CS (Current Setting) in CONFIG2 register */ 45 - #define IS31FL319X_CONFIG2_CS_SHIFT 4 46 - #define IS31FL319X_CONFIG2_CS_MASK 0x7 47 - #define IS31FL319X_CONFIG2_CS_STEP_REF 12 70 + #define IS31FL3196_CONFIG2_CS_SHIFT 4 71 + #define IS31FL3196_CONFIG2_CS_MASK GENMASK(2, 0) 72 + #define IS31FL3196_CONFIG2_CS_STEP_REF 12 48 73 49 - #define IS31FL319X_CURRENT_MIN ((u32)5000) 50 - #define IS31FL319X_CURRENT_MAX ((u32)40000) 51 - #define IS31FL319X_CURRENT_STEP ((u32)5000) 52 - #define IS31FL319X_CURRENT_DEFAULT ((u32)20000) 74 + #define IS31FL3196_CURRENT_uA_MIN 5000 75 + #define IS31FL3196_CURRENT_uA_MAX 40000 76 + #define IS31FL3196_CURRENT_uA_STEP 5000 77 + #define IS31FL3196_CURRENT_uA_DEFAULT 20000 53 78 54 79 /* Audio gain in CONFIG2 register */ 55 - #define IS31FL319X_AUDIO_GAIN_DB_MAX ((u32)21) 56 - #define IS31FL319X_AUDIO_GAIN_DB_STEP ((u32)3) 80 + #define IS31FL3196_AUDIO_GAIN_DB_MAX ((u32)21) 81 + #define IS31FL3196_AUDIO_GAIN_DB_STEP 3 57 82 58 83 /* 59 84 * regmap is used as a cache of chip's register space, ··· 103 78 104 79 struct is31fl319x_chipdef { 105 80 int num_leds; 81 + u8 reset_reg; 82 + const struct regmap_config *is31fl319x_regmap_config; 83 + int (*brightness_set)(struct led_classdev *cdev, enum led_brightness brightness); 84 + u32 current_default; 85 + u32 current_min; 86 + u32 current_max; 87 + bool is_3196or3199; 106 88 }; 107 89 108 - static const struct is31fl319x_chipdef is31fl3190_cdef = { 109 - .num_leds = 1, 90 + static bool is31fl319x_readable_reg(struct device *dev, unsigned int reg) 91 + { 92 + /* we have no readable registers */ 93 + return false; 94 + } 95 + 96 + static bool is31fl3190_volatile_reg(struct device *dev, unsigned int reg) 97 + { 98 + /* volatile registers are not cached */ 99 + switch (reg) { 100 + case IS31FL3190_DATA_UPDATE: 101 + case IS31FL3190_TIME_UPDATE: 102 + case IS31FL3190_RESET: 103 + return true; /* always write-through */ 104 + default: 105 + return false; 106 + } 107 + } 108 + 109 + static const struct reg_default is31fl3190_reg_defaults[] = { 110 + { IS31FL3190_LEDMODE, 0x00 }, 111 + { IS31FL3190_CURRENT, 0x00 }, 112 + { IS31FL3190_PWM(0), 0x00 }, 113 + { IS31FL3190_PWM(1), 0x00 }, 114 + { IS31FL3190_PWM(2), 0x00 }, 110 115 }; 111 116 112 - static const struct is31fl319x_chipdef is31fl3193_cdef = { 113 - .num_leds = 3, 117 + static struct regmap_config is31fl3190_regmap_config = { 118 + .reg_bits = 8, 119 + .val_bits = 8, 120 + .max_register = IS31FL3190_RESET, 121 + .cache_type = REGCACHE_FLAT, 122 + .readable_reg = is31fl319x_readable_reg, 123 + .volatile_reg = is31fl3190_volatile_reg, 124 + .reg_defaults = is31fl3190_reg_defaults, 125 + .num_reg_defaults = ARRAY_SIZE(is31fl3190_reg_defaults), 114 126 }; 115 127 116 - static const struct is31fl319x_chipdef is31fl3196_cdef = { 117 - .num_leds = 6, 128 + static bool is31fl3196_volatile_reg(struct device *dev, unsigned int reg) 129 + { 130 + /* volatile registers are not cached */ 131 + switch (reg) { 132 + case IS31FL3196_DATA_UPDATE: 133 + case IS31FL3196_TIME_UPDATE: 134 + case IS31FL3196_RESET: 135 + return true; /* always write-through */ 136 + default: 137 + return false; 138 + } 139 + } 140 + 141 + static const struct reg_default is31fl3196_reg_defaults[] = { 142 + { IS31FL3196_CONFIG1, 0x00 }, 143 + { IS31FL3196_CONFIG2, 0x00 }, 144 + { IS31FL3196_PWM(0), 0x00 }, 145 + { IS31FL3196_PWM(1), 0x00 }, 146 + { IS31FL3196_PWM(2), 0x00 }, 147 + { IS31FL3196_PWM(3), 0x00 }, 148 + { IS31FL3196_PWM(4), 0x00 }, 149 + { IS31FL3196_PWM(5), 0x00 }, 150 + { IS31FL3196_PWM(6), 0x00 }, 151 + { IS31FL3196_PWM(7), 0x00 }, 152 + { IS31FL3196_PWM(8), 0x00 }, 118 153 }; 119 154 120 - static const struct is31fl319x_chipdef is31fl3199_cdef = { 121 - .num_leds = 9, 155 + static struct regmap_config is31fl3196_regmap_config = { 156 + .reg_bits = 8, 157 + .val_bits = 8, 158 + .max_register = IS31FL3196_REG_CNT, 159 + .cache_type = REGCACHE_FLAT, 160 + .readable_reg = is31fl319x_readable_reg, 161 + .volatile_reg = is31fl3196_volatile_reg, 162 + .reg_defaults = is31fl3196_reg_defaults, 163 + .num_reg_defaults = ARRAY_SIZE(is31fl3196_reg_defaults), 122 164 }; 123 165 124 - static const struct of_device_id of_is31fl319x_match[] = { 125 - { .compatible = "issi,is31fl3190", .data = &is31fl3190_cdef, }, 126 - { .compatible = "issi,is31fl3191", .data = &is31fl3190_cdef, }, 127 - { .compatible = "issi,is31fl3193", .data = &is31fl3193_cdef, }, 128 - { .compatible = "issi,is31fl3196", .data = &is31fl3196_cdef, }, 129 - { .compatible = "issi,is31fl3199", .data = &is31fl3199_cdef, }, 130 - { .compatible = "si-en,sn3199", .data = &is31fl3199_cdef, }, 131 - { } 132 - }; 133 - MODULE_DEVICE_TABLE(of, of_is31fl319x_match); 134 - 135 - static int is31fl319x_brightness_set(struct led_classdev *cdev, 166 + static int is31fl3190_brightness_set(struct led_classdev *cdev, 136 167 enum led_brightness brightness) 137 168 { 138 - struct is31fl319x_led *led = container_of(cdev, struct is31fl319x_led, 139 - cdev); 169 + struct is31fl319x_led *led = container_of(cdev, struct is31fl319x_led, cdev); 140 170 struct is31fl319x_chip *is31 = led->chip; 141 171 int chan = led - is31->leds; 142 172 int ret; 143 173 int i; 144 - u8 ctrl1 = 0, ctrl2 = 0; 174 + u8 ctrl = 0; 145 175 146 - dev_dbg(&is31->client->dev, "%s %d: %d\n", __func__, chan, brightness); 176 + dev_dbg(&is31->client->dev, "channel %d: %d\n", chan, brightness); 147 177 148 178 mutex_lock(&is31->lock); 149 179 150 180 /* update PWM register */ 151 - ret = regmap_write(is31->regmap, IS31FL319X_PWM(chan), brightness); 181 + ret = regmap_write(is31->regmap, IS31FL3190_PWM(chan), brightness); 152 182 if (ret < 0) 153 183 goto out; 154 184 ··· 217 137 * the current setting, we read from the regmap cache 218 138 */ 219 139 220 - ret = regmap_read(is31->regmap, IS31FL319X_PWM(i), &pwm_value); 221 - dev_dbg(&is31->client->dev, "%s read %d: ret=%d: %d\n", 222 - __func__, i, ret, pwm_value); 140 + ret = regmap_read(is31->regmap, IS31FL3190_PWM(i), &pwm_value); 141 + on = ret >= 0 && pwm_value > LED_OFF; 142 + 143 + ctrl |= on << i; 144 + } 145 + 146 + if (ctrl > 0) { 147 + dev_dbg(&is31->client->dev, "power up %02x\n", ctrl); 148 + regmap_write(is31->regmap, IS31FL3190_LEDCONTROL, ctrl); 149 + /* update PWMs */ 150 + regmap_write(is31->regmap, IS31FL3190_DATA_UPDATE, 0x00); 151 + /* enable chip from shut down and enable all channels */ 152 + ret = regmap_write(is31->regmap, IS31FL319X_SHUTDOWN, 0x20); 153 + } else { 154 + dev_dbg(&is31->client->dev, "power down\n"); 155 + /* shut down (no need to clear LEDCONTROL) */ 156 + ret = regmap_write(is31->regmap, IS31FL319X_SHUTDOWN, 0x01); 157 + } 158 + 159 + out: 160 + mutex_unlock(&is31->lock); 161 + 162 + return ret; 163 + } 164 + 165 + static int is31fl3196_brightness_set(struct led_classdev *cdev, 166 + enum led_brightness brightness) 167 + { 168 + struct is31fl319x_led *led = container_of(cdev, struct is31fl319x_led, cdev); 169 + struct is31fl319x_chip *is31 = led->chip; 170 + int chan = led - is31->leds; 171 + int ret; 172 + int i; 173 + u8 ctrl1 = 0, ctrl2 = 0; 174 + 175 + dev_dbg(&is31->client->dev, "channel %d: %d\n", chan, brightness); 176 + 177 + mutex_lock(&is31->lock); 178 + 179 + /* update PWM register */ 180 + ret = regmap_write(is31->regmap, IS31FL3196_PWM(chan), brightness); 181 + if (ret < 0) 182 + goto out; 183 + 184 + /* read current brightness of all PWM channels */ 185 + for (i = 0; i < is31->cdef->num_leds; i++) { 186 + unsigned int pwm_value; 187 + bool on; 188 + 189 + /* 190 + * since neither cdev nor the chip can provide 191 + * the current setting, we read from the regmap cache 192 + */ 193 + 194 + ret = regmap_read(is31->regmap, IS31FL3196_PWM(i), &pwm_value); 223 195 on = ret >= 0 && pwm_value > LED_OFF; 224 196 225 197 if (i < 3) ··· 285 153 if (ctrl1 > 0 || ctrl2 > 0) { 286 154 dev_dbg(&is31->client->dev, "power up %02x %02x\n", 287 155 ctrl1, ctrl2); 288 - regmap_write(is31->regmap, IS31FL319X_CTRL1, ctrl1); 289 - regmap_write(is31->regmap, IS31FL319X_CTRL2, ctrl2); 156 + regmap_write(is31->regmap, IS31FL3196_CTRL1, ctrl1); 157 + regmap_write(is31->regmap, IS31FL3196_CTRL2, ctrl2); 290 158 /* update PWMs */ 291 - regmap_write(is31->regmap, IS31FL319X_DATA_UPDATE, 0x00); 159 + regmap_write(is31->regmap, IS31FL3196_DATA_UPDATE, 0x00); 292 160 /* enable chip from shut down */ 293 161 ret = regmap_write(is31->regmap, IS31FL319X_SHUTDOWN, 0x01); 294 162 } else { ··· 303 171 return ret; 304 172 } 305 173 306 - static int is31fl319x_parse_child_dt(const struct device *dev, 307 - const struct device_node *child, 308 - struct is31fl319x_led *led) 174 + static const struct is31fl319x_chipdef is31fl3190_cdef = { 175 + .num_leds = 1, 176 + .reset_reg = IS31FL3190_RESET, 177 + .is31fl319x_regmap_config = &is31fl3190_regmap_config, 178 + .brightness_set = is31fl3190_brightness_set, 179 + .current_default = IS31FL3190_CURRENT_uA_DEFAULT, 180 + .current_min = IS31FL3190_CURRENT_uA_MIN, 181 + .current_max = IS31FL3190_CURRENT_uA_MAX, 182 + .is_3196or3199 = false, 183 + }; 184 + 185 + static const struct is31fl319x_chipdef is31fl3193_cdef = { 186 + .num_leds = 3, 187 + .reset_reg = IS31FL3190_RESET, 188 + .is31fl319x_regmap_config = &is31fl3190_regmap_config, 189 + .brightness_set = is31fl3190_brightness_set, 190 + .current_default = IS31FL3190_CURRENT_uA_DEFAULT, 191 + .current_min = IS31FL3190_CURRENT_uA_MIN, 192 + .current_max = IS31FL3190_CURRENT_uA_MAX, 193 + .is_3196or3199 = false, 194 + }; 195 + 196 + static const struct is31fl319x_chipdef is31fl3196_cdef = { 197 + .num_leds = 6, 198 + .reset_reg = IS31FL3196_RESET, 199 + .is31fl319x_regmap_config = &is31fl3196_regmap_config, 200 + .brightness_set = is31fl3196_brightness_set, 201 + .current_default = IS31FL3196_CURRENT_uA_DEFAULT, 202 + .current_min = IS31FL3196_CURRENT_uA_MIN, 203 + .current_max = IS31FL3196_CURRENT_uA_MAX, 204 + .is_3196or3199 = true, 205 + }; 206 + 207 + static const struct is31fl319x_chipdef is31fl3199_cdef = { 208 + .num_leds = 9, 209 + .reset_reg = IS31FL3196_RESET, 210 + .is31fl319x_regmap_config = &is31fl3196_regmap_config, 211 + .brightness_set = is31fl3196_brightness_set, 212 + .current_default = IS31FL3196_CURRENT_uA_DEFAULT, 213 + .current_min = IS31FL3196_CURRENT_uA_MIN, 214 + .current_max = IS31FL3196_CURRENT_uA_MAX, 215 + .is_3196or3199 = true, 216 + }; 217 + 218 + static const struct of_device_id of_is31fl319x_match[] = { 219 + { .compatible = "issi,is31fl3190", .data = &is31fl3190_cdef, }, 220 + { .compatible = "issi,is31fl3191", .data = &is31fl3190_cdef, }, 221 + { .compatible = "issi,is31fl3193", .data = &is31fl3193_cdef, }, 222 + { .compatible = "issi,is31fl3196", .data = &is31fl3196_cdef, }, 223 + { .compatible = "issi,is31fl3199", .data = &is31fl3199_cdef, }, 224 + { .compatible = "si-en,sn3190", .data = &is31fl3190_cdef, }, 225 + { .compatible = "si-en,sn3191", .data = &is31fl3190_cdef, }, 226 + { .compatible = "si-en,sn3193", .data = &is31fl3193_cdef, }, 227 + { .compatible = "si-en,sn3196", .data = &is31fl3196_cdef, }, 228 + { .compatible = "si-en,sn3199", .data = &is31fl3199_cdef, }, 229 + { } 230 + }; 231 + MODULE_DEVICE_TABLE(of, of_is31fl319x_match); 232 + 233 + static int is31fl319x_parse_child_fw(const struct device *dev, 234 + const struct fwnode_handle *child, 235 + struct is31fl319x_led *led, 236 + struct is31fl319x_chip *is31) 309 237 { 310 238 struct led_classdev *cdev = &led->cdev; 311 239 int ret; 312 240 313 - if (of_property_read_string(child, "label", &cdev->name)) 314 - cdev->name = child->name; 241 + if (fwnode_property_read_string(child, "label", &cdev->name)) 242 + cdev->name = fwnode_get_name(child); 315 243 316 - ret = of_property_read_string(child, "linux,default-trigger", 317 - &cdev->default_trigger); 244 + ret = fwnode_property_read_string(child, "linux,default-trigger", &cdev->default_trigger); 318 245 if (ret < 0 && ret != -EINVAL) /* is optional */ 319 246 return ret; 320 247 321 - led->max_microamp = IS31FL319X_CURRENT_DEFAULT; 322 - ret = of_property_read_u32(child, "led-max-microamp", 323 - &led->max_microamp); 248 + led->max_microamp = is31->cdef->current_default; 249 + ret = fwnode_property_read_u32(child, "led-max-microamp", &led->max_microamp); 324 250 if (!ret) { 325 - if (led->max_microamp < IS31FL319X_CURRENT_MIN) 251 + if (led->max_microamp < is31->cdef->current_min) 326 252 return -EINVAL; /* not supported */ 327 253 led->max_microamp = min(led->max_microamp, 328 - IS31FL319X_CURRENT_MAX); 254 + is31->cdef->current_max); 329 255 } 330 256 331 257 return 0; 332 258 } 333 259 334 - static int is31fl319x_parse_dt(struct device *dev, 335 - struct is31fl319x_chip *is31) 260 + static int is31fl319x_parse_fw(struct device *dev, struct is31fl319x_chip *is31) 336 261 { 337 - struct device_node *np = dev_of_node(dev), *child; 262 + struct fwnode_handle *fwnode = dev_fwnode(dev), *child; 338 263 int count; 339 264 int ret; 340 265 341 - if (!np) 342 - return -ENODEV; 343 - 344 - is31->shutdown_gpio = devm_gpiod_get_optional(dev, 345 - "shutdown", 346 - GPIOD_OUT_HIGH); 347 - if (IS_ERR(is31->shutdown_gpio)) { 348 - ret = PTR_ERR(is31->shutdown_gpio); 349 - dev_err(dev, "Failed to get shutdown gpio: %d\n", ret); 350 - return ret; 351 - } 266 + is31->shutdown_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); 267 + if (IS_ERR(is31->shutdown_gpio)) 268 + return dev_err_probe(dev, PTR_ERR(is31->shutdown_gpio), 269 + "Failed to get shutdown gpio\n"); 352 270 353 271 is31->cdef = device_get_match_data(dev); 354 272 355 - count = of_get_available_child_count(np); 273 + count = 0; 274 + fwnode_for_each_available_child_node(fwnode, child) 275 + count++; 356 276 357 277 dev_dbg(dev, "probing with %d leds defined in DT\n", count); 358 278 359 - if (!count || count > is31->cdef->num_leds) { 360 - dev_err(dev, "Number of leds defined must be between 1 and %u\n", 361 - is31->cdef->num_leds); 362 - return -ENODEV; 363 - } 279 + if (!count || count > is31->cdef->num_leds) 280 + return dev_err_probe(dev, -ENODEV, 281 + "Number of leds defined must be between 1 and %u\n", 282 + is31->cdef->num_leds); 364 283 365 - for_each_available_child_of_node(np, child) { 284 + fwnode_for_each_available_child_node(fwnode, child) { 366 285 struct is31fl319x_led *led; 367 286 u32 reg; 368 287 369 - ret = of_property_read_u32(child, "reg", &reg); 288 + ret = fwnode_property_read_u32(child, "reg", &reg); 370 289 if (ret) { 371 - dev_err(dev, "Failed to read led 'reg' property\n"); 290 + ret = dev_err_probe(dev, ret, "Failed to read led 'reg' property\n"); 372 291 goto put_child_node; 373 292 } 374 293 375 294 if (reg < 1 || reg > is31->cdef->num_leds) { 376 - dev_err(dev, "invalid led reg %u\n", reg); 377 - ret = -EINVAL; 295 + ret = dev_err_probe(dev, -EINVAL, "invalid led reg %u\n", reg); 378 296 goto put_child_node; 379 297 } 380 298 381 299 led = &is31->leds[reg - 1]; 382 300 383 301 if (led->configured) { 384 - dev_err(dev, "led %u is already configured\n", reg); 385 - ret = -EINVAL; 302 + ret = dev_err_probe(dev, -EINVAL, "led %u is already configured\n", reg); 386 303 goto put_child_node; 387 304 } 388 305 389 - ret = is31fl319x_parse_child_dt(dev, child, led); 306 + ret = is31fl319x_parse_child_fw(dev, child, led, is31); 390 307 if (ret) { 391 - dev_err(dev, "led %u DT parsing failed\n", reg); 308 + ret = dev_err_probe(dev, ret, "led %u DT parsing failed\n", reg); 392 309 goto put_child_node; 393 310 } 394 311 ··· 445 264 } 446 265 447 266 is31->audio_gain_db = 0; 448 - ret = of_property_read_u32(np, "audio-gain-db", &is31->audio_gain_db); 449 - if (!ret) 450 - is31->audio_gain_db = min(is31->audio_gain_db, 451 - IS31FL319X_AUDIO_GAIN_DB_MAX); 267 + if (is31->cdef->is_3196or3199) { 268 + ret = fwnode_property_read_u32(fwnode, "audio-gain-db", &is31->audio_gain_db); 269 + if (!ret) 270 + is31->audio_gain_db = min(is31->audio_gain_db, 271 + IS31FL3196_AUDIO_GAIN_DB_MAX); 272 + } 452 273 453 274 return 0; 454 275 455 276 put_child_node: 456 - of_node_put(child); 277 + fwnode_handle_put(child); 457 278 return ret; 458 279 } 459 280 460 - static bool is31fl319x_readable_reg(struct device *dev, unsigned int reg) 461 - { /* we have no readable registers */ 462 - return false; 463 - } 464 - 465 - static bool is31fl319x_volatile_reg(struct device *dev, unsigned int reg) 466 - { /* volatile registers are not cached */ 467 - switch (reg) { 468 - case IS31FL319X_DATA_UPDATE: 469 - case IS31FL319X_TIME_UPDATE: 470 - case IS31FL319X_RESET: 471 - return true; /* always write-through */ 281 + static inline int is31fl3190_microamp_to_cs(struct device *dev, u32 microamp) 282 + { 283 + switch (microamp) { 284 + case 5000: 285 + return IS31FL3190_CURRENT_5_mA; 286 + case 10000: 287 + return IS31FL3190_CURRENT_10_mA; 288 + case 17500: 289 + return IS31FL3190_CURRENT_17dot5_mA; 290 + case 30000: 291 + return IS31FL3190_CURRENT_30_mA; 292 + case 42000: 293 + return IS31FL3190_CURRENT_42_mA; 472 294 default: 473 - return false; 295 + dev_warn(dev, "Unsupported current value: %d, using 5000 µA!\n", microamp); 296 + return IS31FL3190_CURRENT_5_mA; 474 297 } 475 298 } 476 299 477 - static const struct reg_default is31fl319x_reg_defaults[] = { 478 - { IS31FL319X_CONFIG1, 0x00}, 479 - { IS31FL319X_CONFIG2, 0x00}, 480 - { IS31FL319X_PWM(0), 0x00}, 481 - { IS31FL319X_PWM(1), 0x00}, 482 - { IS31FL319X_PWM(2), 0x00}, 483 - { IS31FL319X_PWM(3), 0x00}, 484 - { IS31FL319X_PWM(4), 0x00}, 485 - { IS31FL319X_PWM(5), 0x00}, 486 - { IS31FL319X_PWM(6), 0x00}, 487 - { IS31FL319X_PWM(7), 0x00}, 488 - { IS31FL319X_PWM(8), 0x00}, 489 - }; 300 + static inline int is31fl3196_microamp_to_cs(struct device *dev, u32 microamp) 301 + { 302 + /* round down to nearest supported value (range check done by caller) */ 303 + u32 step = microamp / IS31FL3196_CURRENT_uA_STEP; 490 304 491 - static struct regmap_config regmap_config = { 492 - .reg_bits = 8, 493 - .val_bits = 8, 494 - .max_register = IS31FL319X_REG_CNT, 495 - .cache_type = REGCACHE_FLAT, 496 - .readable_reg = is31fl319x_readable_reg, 497 - .volatile_reg = is31fl319x_volatile_reg, 498 - .reg_defaults = is31fl319x_reg_defaults, 499 - .num_reg_defaults = ARRAY_SIZE(is31fl319x_reg_defaults), 500 - }; 501 - 502 - static inline int is31fl319x_microamp_to_cs(struct device *dev, u32 microamp) 503 - { /* round down to nearest supported value (range check done by caller) */ 504 - u32 step = microamp / IS31FL319X_CURRENT_STEP; 505 - 506 - return ((IS31FL319X_CONFIG2_CS_STEP_REF - step) & 507 - IS31FL319X_CONFIG2_CS_MASK) << 508 - IS31FL319X_CONFIG2_CS_SHIFT; /* CS encoding */ 305 + return ((IS31FL3196_CONFIG2_CS_STEP_REF - step) & 306 + IS31FL3196_CONFIG2_CS_MASK) << 307 + IS31FL3196_CONFIG2_CS_SHIFT; /* CS encoding */ 509 308 } 510 309 511 - static inline int is31fl319x_db_to_gain(u32 dezibel) 512 - { /* round down to nearest supported value (range check done by caller) */ 513 - return dezibel / IS31FL319X_AUDIO_GAIN_DB_STEP; 310 + static inline int is31fl3196_db_to_gain(u32 dezibel) 311 + { 312 + /* round down to nearest supported value (range check done by caller) */ 313 + return dezibel / IS31FL3196_AUDIO_GAIN_DB_STEP; 514 314 } 515 315 516 - static int is31fl319x_probe(struct i2c_client *client, 517 - const struct i2c_device_id *id) 316 + static int is31fl319x_probe(struct i2c_client *client) 518 317 { 519 318 struct is31fl319x_chip *is31; 520 319 struct device *dev = &client->dev; 521 320 int err; 522 321 int i = 0; 523 - u32 aggregated_led_microamp = IS31FL319X_CURRENT_MAX; 322 + u32 aggregated_led_microamp; 524 323 525 324 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 526 325 return -EIO; ··· 510 349 return -ENOMEM; 511 350 512 351 mutex_init(&is31->lock); 513 - 514 - err = is31fl319x_parse_dt(&client->dev, is31); 352 + err = devm_add_action(dev, (void (*)(void *))mutex_destroy, &is31->lock); 515 353 if (err) 516 - goto free_mutex; 354 + return err; 355 + 356 + err = is31fl319x_parse_fw(&client->dev, is31); 357 + if (err) 358 + return err; 517 359 518 360 if (is31->shutdown_gpio) { 519 361 gpiod_direction_output(is31->shutdown_gpio, 0); ··· 525 361 } 526 362 527 363 is31->client = client; 528 - is31->regmap = devm_regmap_init_i2c(client, &regmap_config); 529 - if (IS_ERR(is31->regmap)) { 530 - dev_err(&client->dev, "failed to allocate register map\n"); 531 - err = PTR_ERR(is31->regmap); 532 - goto free_mutex; 533 - } 364 + is31->regmap = devm_regmap_init_i2c(client, is31->cdef->is31fl319x_regmap_config); 365 + if (IS_ERR(is31->regmap)) 366 + return dev_err_probe(dev, PTR_ERR(is31->regmap), "failed to allocate register map\n"); 534 367 535 368 i2c_set_clientdata(client, is31); 536 369 537 370 /* check for write-reply from chip (we can't read any registers) */ 538 - err = regmap_write(is31->regmap, IS31FL319X_RESET, 0x00); 539 - if (err < 0) { 540 - dev_err(&client->dev, "no response from chip write: err = %d\n", 541 - err); 542 - err = -EIO; /* does not answer */ 543 - goto free_mutex; 544 - } 371 + err = regmap_write(is31->regmap, is31->cdef->reset_reg, 0x00); 372 + if (err < 0) 373 + return dev_err_probe(dev, err, "no response from chip write\n"); 545 374 546 375 /* 547 376 * Kernel conventions require per-LED led-max-microamp property. 548 377 * But the chip does not allow to limit individual LEDs. 549 378 * So we take minimum from all subnodes for safety of hardware. 550 379 */ 380 + aggregated_led_microamp = is31->cdef->current_max; 551 381 for (i = 0; i < is31->cdef->num_leds; i++) 552 382 if (is31->leds[i].configured && 553 383 is31->leds[i].max_microamp < aggregated_led_microamp) 554 384 aggregated_led_microamp = is31->leds[i].max_microamp; 555 385 556 - regmap_write(is31->regmap, IS31FL319X_CONFIG2, 557 - is31fl319x_microamp_to_cs(dev, aggregated_led_microamp) | 558 - is31fl319x_db_to_gain(is31->audio_gain_db)); 386 + if (is31->cdef->is_3196or3199) 387 + regmap_write(is31->regmap, IS31FL3196_CONFIG2, 388 + is31fl3196_microamp_to_cs(dev, aggregated_led_microamp) | 389 + is31fl3196_db_to_gain(is31->audio_gain_db)); 390 + else 391 + regmap_update_bits(is31->regmap, IS31FL3190_CURRENT, IS31FL3190_CURRENT_MASK, 392 + is31fl3190_microamp_to_cs(dev, aggregated_led_microamp)); 559 393 560 394 for (i = 0; i < is31->cdef->num_leds; i++) { 561 395 struct is31fl319x_led *led = &is31->leds[i]; ··· 562 400 continue; 563 401 564 402 led->chip = is31; 565 - led->cdev.brightness_set_blocking = is31fl319x_brightness_set; 403 + led->cdev.brightness_set_blocking = is31->cdef->brightness_set; 566 404 567 405 err = devm_led_classdev_register(&client->dev, &led->cdev); 568 406 if (err < 0) 569 - goto free_mutex; 407 + return err; 570 408 } 571 409 572 - return 0; 573 - 574 - free_mutex: 575 - mutex_destroy(&is31->lock); 576 - return err; 577 - } 578 - 579 - static int is31fl319x_remove(struct i2c_client *client) 580 - { 581 - struct is31fl319x_chip *is31 = i2c_get_clientdata(client); 582 - 583 - mutex_destroy(&is31->lock); 584 410 return 0; 585 411 } 586 412 ··· 582 432 { "is31fl3193" }, 583 433 { "is31fl3196" }, 584 434 { "is31fl3199" }, 435 + { "sn3190" }, 436 + { "sn3191" }, 437 + { "sn3193" }, 438 + { "sn3196" }, 585 439 { "sn3199" }, 586 440 {}, 587 441 }; ··· 594 440 static struct i2c_driver is31fl319x_driver = { 595 441 .driver = { 596 442 .name = "leds-is31fl319x", 597 - .of_match_table = of_match_ptr(of_is31fl319x_match), 443 + .of_match_table = of_is31fl319x_match, 598 444 }, 599 - .probe = is31fl319x_probe, 600 - .remove = is31fl319x_remove, 445 + .probe_new = is31fl319x_probe, 601 446 .id_table = is31fl319x_id, 602 447 }; 603 448
+1 -3
drivers/leds/leds-turris-omnia.c
··· 239 239 led += ret; 240 240 } 241 241 242 - if (devm_device_add_groups(dev, omnia_led_controller_groups)) 243 - dev_warn(dev, "Could not add attribute group!\n"); 244 - 245 242 return 0; 246 243 } 247 244 ··· 280 283 .driver = { 281 284 .name = "leds-turris-omnia", 282 285 .of_match_table = of_omnia_leds_match, 286 + .dev_groups = omnia_led_controller_groups, 283 287 }, 284 288 }; 285 289
+6 -2
drivers/leds/rgb/leds-pwm-multicolor.c
··· 19 19 struct pwm_led { 20 20 struct pwm_device *pwm; 21 21 struct pwm_state state; 22 + bool active_low; 22 23 }; 23 24 24 25 struct pwm_mc_led { ··· 45 44 duty = priv->leds[i].state.period; 46 45 duty *= mc_cdev->subled_info[i].brightness; 47 46 do_div(duty, cdev->max_brightness); 47 + 48 + if (priv->leds[i].active_low) 49 + duty = priv->leds[i].state.period - duty; 48 50 49 51 priv->leds[i].state.duty_cycle = duty; 50 52 priv->leds[i].state.enabled = duty > 0; ··· 76 72 pwmled = &priv->leds[priv->mc_cdev.num_colors]; 77 73 pwmled->pwm = devm_fwnode_pwm_get(dev, fwnode, NULL); 78 74 if (IS_ERR(pwmled->pwm)) { 79 - ret = PTR_ERR(pwmled->pwm); 80 - dev_err(dev, "unable to request PWM: %d\n", ret); 75 + ret = dev_err_probe(dev, PTR_ERR(pwmled->pwm), "unable to request PWM\n"); 81 76 goto release_fwnode; 82 77 } 83 78 pwm_init_state(pwmled->pwm, &pwmled->state); 79 + pwmled->active_low = fwnode_property_read_bool(fwnode, "active-low"); 84 80 85 81 ret = fwnode_property_read_u32(fwnode, "color", &color); 86 82 if (ret) {