Resend LED patches
Subsystems (4)
cover Resend LED patches
Linus Walleij suggested me to send these patches to SoC tree [1] instead. So I'm doing it.
This patch series contains LED patches which are on the linux-leds mailing list for a long time without any future movement. Could you please handle them here via SoC tree? Thanks.
Marek Behún (3):
leds: turris-omnia: support HW controlled mode via private trigger
leds: turris-omnia: initialize multi-intensity to full
leds: turris-omnia: change max brightness from 255 to 1
Pali Rohár (5):
dt-bindings: leds: register-bit-led: Add active-low property
leds: syscon: Implement support for active-low property powerpc/85xx: DTS: Add CPLD definitions for P1021RDB Combo Board CPL
Design
dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
leds: Add support for Turris 1.x LEDs
.../testing/sysfs-class-led-driver-turris1x | 31 ++ .../bindings/leds/cznic,turris1x-leds.yaml | 118 +++++ .../bindings/leds/register-bit-led.yaml | 5 + arch/powerpc/boot/dts/fsl/p1020mbg-pc.dtsi | 92 ++++ arch/powerpc/boot/dts/fsl/p1020mbg-pc_32b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020mbg-pc_36b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020rdb-pd.dts | 44 +- arch/powerpc/boot/dts/fsl/p1020utm-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1020utm-pc_32b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1020utm-pc_36b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1021rdb-pc_32b.dts | 5 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc_36b.dts | 5 +- arch/powerpc/boot/dts/fsl/p2020rdb-pc.dtsi | 33 +- drivers/leds/Kconfig | 10 + drivers/leds/Makefile | 1 + drivers/leds/leds-syscon.c | 14 +- drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ drivers/leds/leds-turris-omnia.c | 46 +- 19 files changed, 945 insertions(+), 27 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-led-driver-turris1x create mode 100644 Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yaml create mode 100644 drivers/leds/leds-turris-1x.c
Signature · 1 line
2.20.1
PATCH RESEND 1/8 dt-bindings: leds: register-bit-led: Add active-low property
Allow to define inverted logic (0 - enable LED, 1 - disable LED) via active-low property.
--- Documentation/devicetree/bindings/leds/register-bit-led.yaml | 5 +++++ 1 file changed, 5 insertions(+)
Documentation/devicetree/bindings/leds/register-bit-led.yaml +5 -0
@@ -43,6 +43,11 @@ properties: 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 ] + active-low: + $ref: /schemas/types.yaml#/definitions/flag + description: + LED is ON when bit in register is not set + offset: description: register offset to the register controlling this LED
Signature · 1 line
2.20.1
Lee Jones
maintainerRe: [PATCH RESEND 1/8] dt-bindings: leds: register-bit-led: Add active-low property
Quoted 8 lines · Pali Rohár
Allow to define inverted logic (0 - enable LED, 1 - disable LED) via active-low property.
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Linus Walleij <[email protected]>--- Documentation/devicetree/bindings/leds/register-bit-led.yaml | 5 +++++ 1 file changed, 5 insertions(+)
Needs a DT Ack (now Cc:ed)
Quoted 19 lines
Documentation/devicetree/bindings/leds/register-bit-led.yaml +5
-0@@ -43,6 +43,11 @@ properties: 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 ] + active-low: + $ref: /schemas/types.yaml#/definitions/flag + description: + LED is ON when bit in register is not set + offset: description: register offset to the register controlling this LEDSignature · 1 line
2.20.1
Signature · 1 line
Lee Jones [李琼斯]
Lee Jones
maintainerRe: [PATCH RESEND 1/8] dt-bindings: leds: register-bit-led: Add active-low property
Quoted 5 lines · Lee Jones
Quoted 3 lines · Pali Rohár
Allow to define inverted logic (0 - enable LED, 1 - disable LED) via active-low property.
Quoted 7 lines
Quoted 5 lines
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Linus Walleij <[email protected]>--- Documentation/devicetree/bindings/leds/register-bit-led.yaml | 5 +++++ 1 file changed, 5 insertions(+)Needs a DT Ack (now Cc:ed)
I can't do anything with this set until we have a DT Ack.
If you don't receive one soon, I'd suggest resending the set again with all of the DT people on Cc that it should have been sent to in the first place.
Quoted 22 lines
Quoted 19 lines
Documentation/devicetree/bindings/leds/register-bit-led.yaml +5
-0@@ -43,6 +43,11 @@ properties: 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 ] + active-low: + $ref: /schemas/types.yaml#/definitions/flag + description: + LED is ON when bit in register is not set + offset: description: register offset to the register controlling this LEDSignature · 1 line
2.20.1Signature · 1 line
Lee Jones [李琼斯]
Signature · 1 line
Lee Jones [李琼斯]
Re: [PATCH RESEND 1/8] dt-bindings: leds: register-bit-led: Add active-low property
Quoted 13 lines · On Thursday 23 February 2023 14:22:52 Lee Jones wrote:
Quoted 11 lines · Lee Jones
Quoted 8 lines · Pali Rohár
Allow to define inverted logic (0 - enable LED, 1 - disable LED) via active-low property.
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Linus Walleij <[email protected]>--- Documentation/devicetree/bindings/leds/register-bit-led.yaml | 5 +++++ 1 file changed, 5 insertions(+)
Quoted 7 lines
Quoted 1 line
Needs a DT Ack (now Cc:ed)
I can't do anything with this set until we have a DT Ack.
If you don't receive one soon, I'd suggest resending the set again with all of the DT people on Cc that it should have been sent to in the first place.
(Re)Sending one email multiple times is against email etiquette, moreover it is spam technique and reason for marking sender on the blacklist.
Moreover I have already sent it more than one time. DT people are known to not respond to patches and pull requests and I have no motivation to send reminder emails for them for more than half of year.
So I would suggest to not send emails to people who just do not want to receive or read emails. It is logical reaction.
This patch is here for more than 6 months, so I do not see reason why to wait for Godot. Rather move forward than stepping at the same position.
Quoted 25 lines
Quoted 22 lines
Quoted 19 lines
Documentation/devicetree/bindings/leds/register-bit-led.yaml +5
-0@@ -43,6 +43,11 @@ properties: 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000 ] + active-low: + $ref: /schemas/types.yaml#/definitions/flag + description: + LED is ON when bit in register is not set + offset: description: register offset to the register controlling this LEDSignature · 1 line
2.20.1Signature · 1 line
Lee Jones [李琼斯]Signature · 1 line
Lee Jones [李琼斯]
Re: [PATCH RESEND 1/8] dt-bindings: leds: register-bit-led: Add active-low property
Quoted 18 lines · Pali Rohár
Quoted 17 lines · On Thursday 23 February 2023 14:22:52 Lee Jones wrote:
Quoted 5 lines · Lee Jones
Quoted 3 lines · Pali Rohár
Allow to define inverted logic (0 - enable LED, 1 - disable LED) via active-low property.
Quoted 7 lines
Quoted 5 lines
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Linus Walleij <[email protected]>--- Documentation/devicetree/bindings/leds/register-bit-led.yaml | 5 +++++ 1 file changed, 5 insertions(+)Needs a DT Ack (now Cc:ed)
I can't do anything with this set until we have a DT Ack.
Quoted 7 lines
Quoted 3 lines
If you don't receive one soon, I'd suggest resending the set again with all of the DT people on Cc that it should have been sent to in the first place.
(Re)Sending one email multiple times is against email etiquette, moreover it is spam technique and reason for marking sender on the blacklist.
No problem on the kernel mailing lists actually, we love to mail bomb each other here. Yeah maybe we are a bit weird :/
Quoted 9 lines
Moreover I have already sent it more than one time. DT people are known to not respond to patches and pull requests and I have no motivation to send reminder emails for them for more than half of year.
So I would suggest to not send emails to people who just do not want to receive or read emails. It is logical reaction.
This patch is here for more than 6 months, so I do not see reason why to wait for Godot. Rather move forward than stepping at the same position.
I understand that it is annoying.
In my experience Krzysztof and Rob (now added on To) are usually quite responsive and helpful, so something must have made them miss it I think.
As subsystem maintainer, if the DT reviewers haven't said anything in ~2 weeks I tend to sanity check the binding as best I can and then merge it. The bigger and more complex it is the more hesitant I get to do this...
Yours,
Linus Walleij
Re: [PATCH RESEND 1/8] dt-bindings: leds: register-bit-led: Add active-low property
Quoted 23 lines · Linus Walleij
Quoted 22 lines · Pali Rohár
Quoted 20 lines · On Thursday 23 February 2023 14:22:52 Lee Jones wrote:
Quoted 5 lines · Lee Jones
Quoted 3 lines · Pali Rohár
Allow to define inverted logic (0 - enable LED, 1 - disable LED) via active-low property.
Quoted 7 lines
Quoted 5 lines
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Linus Walleij <[email protected]>--- Documentation/devicetree/bindings/leds/register-bit-led.yaml | 5 +++++ 1 file changed, 5 insertions(+)Needs a DT Ack (now Cc:ed)
I can't do anything with this set until we have a DT Ack.
If you don't receive one soon, I'd suggest resending the set again with all of the DT people on Cc that it should have been sent to in the first place.
Quoted 10 lines
Quoted 3 lines
(Re)Sending one email multiple times is against email etiquette, moreover it is spam technique and reason for marking sender on the blacklist.
No problem on the kernel mailing lists actually, we love to mail bomb each other here. Yeah maybe we are a bit weird :/
Quoted 3 lines
Moreover I have already sent it more than one time. DT people are known to not respond to patches and pull requests and I have no motivation to send reminder emails for them for more than half of year.
Is this a joke? You got here response within one day!
Sent: 18th of August
Reviewed-by: 19th of August
https://lore.kernel.org/all/[email protected]/
You ignored the tag and then ignored the process and not Cc'ed us. Yet you complain that someone did not respond to your emails. Really?
Quoted 9 lines
Quoted 6 lines
So I would suggest to not send emails to people who just do not want to receive or read emails. It is logical reaction.
This patch is here for more than 6 months, so I do not see reason why to wait for Godot. Rather move forward than stepping at the same position.
I understand that it is annoying.
Quoted 8 lines
In my experience Krzysztof and Rob (now added on To) are usually quite responsive and helpful, so something must have made them miss it I think.
As subsystem maintainer, if the DT reviewers haven't said anything in ~2 weeks I tend to sanity check the binding as best I can and then merge it. The bigger and more complex it is the more hesitant I get to do this...
Yeah... this patch was never sent to us, thus regardless how hard we work, it would be quite difficult to answer emails which we never received.
Best regards,
Krzysztof
PATCH RESEND 2/8 leds: syscon: Implement support for active-low property
In reply to Pali RohárThis new active-low property specify that LED has inverted logic (0 - enable LED, 1 - disable LED).
--- drivers/leds/leds-syscon.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/leds/leds-syscon.c +10 -4
@@ -29,6 +29,7 @@ struct syscon_led {struct regmap *map;u32 offset;u32 mask; +bool active_low;bool state; };
@@ -41,10 +42,10 @@ static void syscon_led_set(struct led_classdev *led_cdev,int ret;if (value ==LED_OFF ) { - val =0 ; + val = sled->active_low ? sled->mask :0 ; sled->state = false; }else { - val = sled->mask; + val = sled->active_low ?0 : sled->mask; sled->state = true; }
@@ -85,6 +86,8 @@ static int syscon_led_probe(struct platform_device *pdev)return -EINVAL ;if (of_property_read_u32 (np,"mask" , &sled->mask))return -EINVAL ; +if (of_find_property (np,"active-low" ,NULL )) + sled->active_low = true; state =of_get_property (np,"default-state" ,NULL );if (state) {
@@ -95,17 +98,20 @@ static int syscon_led_probe(struct platform_device *pdev)if (ret <0 )return ret; sled->state = !!(val & sled->mask); +if (sled->active_low) + sled->state = !sled->state; }else if (!strcmp (state,"on" )) { sled->state = true; ret =regmap_update_bits (map, sled->offset, sled->mask, - sled->mask); + sled->active_low ?0 : sled->mask);if (ret <0 )return ret; }else { sled->state = false; ret =regmap_update_bits (map, sled->offset, - sled->mask,0 ); + sled->mask, + sled->active_low ? sled->mask :0 );if (ret <0 )return ret; }
Signature · 1 line
2.20.1
Re: [PATCH RESEND 2/8] leds: syscon: Implement support for active-low property
Quoted 8 lines · Pali Rohár
This new active-low property specify that LED has inverted logic (0 - enable LED, 1 - disable LED).
Signed-off-by Pali Rohár <[email protected]>Acked-by Linus Walleij <[email protected]>--- drivers/leds/leds-syscon.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
Quoted 60 lines
drivers/leds/leds-syscon.c +10
-4@@ -29,6 +29,7 @@ struct syscon_led {struct regmap *map;u32 offset;u32 mask; +bool active_low;bool state; };@@ -41,10 +42,10 @@ static void syscon_led_set(struct led_classdev *led_cdev,int ret;if (value ==LED_OFF ) { - val =0 ; + val = sled->active_low ? sled->mask :0 ; sled->state = false; }else { - val = sled->mask; + val = sled->active_low ?0 : sled->mask; sled->state = true; }@@ -85,6 +86,8 @@ static int syscon_led_probe(struct platform_device *pdev)return -EINVAL ;if (of_property_read_u32 (np,"mask" , &sled->mask))return -EINVAL ; +if (of_find_property (np,"active-low" ,NULL )) + sled->active_low = true; state =of_get_property (np,"default-state" ,NULL );if (state) {@@ -95,17 +98,20 @@ static int syscon_led_probe(struct platform_device *pdev)if (ret <0 )return ret; sled->state = !!(val & sled->mask); +if (sled->active_low) + sled->state = !sled->state; }else if (!strcmp (state,"on" )) { sled->state = true; ret =regmap_update_bits (map, sled->offset, sled->mask, - sled->mask); + sled->active_low ?0 : sled->mask);if (ret <0 )return ret; }else { sled->state = false; ret =regmap_update_bits (map, sled->offset, - sled->mask,0 ); + sled->mask, + sled->active_low ? sled->mask :0 );if (ret <0 )return ret; }Signature · 1 line
2.20.1
Signature · 1 line
Lee Jones [李琼斯]
PATCH RESEND 3/8 powerpc/85xx: DTS: Add CPLD definitions for P1021RDB Combo Board CPL Design
In reply to Pali RohárP1021RDB Combo Board CPLD Design is used on following Freescale boards:
P1021RDB-PC, P1020RDB-PD, P1020MBG-PC, P1020UTM-PC and P2020RDB-PCA.
Add CPLD definitions for all these boards for which already exist DTS file.
CPLD has bank size 128kB, it is connected via CS3 on LBC and mapped to memory range 0xFFA00000~0xFFA1FFFF.
As CPLD firmware is common on all these boards, use just one compatible string "fsl,p1021rdb-pc-cpld".
In some DTS files is CPLD already defined, but definition is either incomplete or wrong. So fix it.
All these boards have via CPLD connected max6370 watchdog at offset 0x2 with GPIO 11, status led at offset 0x8 and reset controller at offset 0xd. Additionally P1020MBG-PC and P1020RDB-PD boards have FXO led at offset 0x9 and FXS leds at offset 0xa.
--- arch/powerpc/boot/dts/fsl/p1020mbg-pc.dtsi | 92 +++++++++++++++++++ arch/powerpc/boot/dts/fsl/p1020mbg-pc_32b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020mbg-pc_36b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020rdb-pd.dts | 44 +++++++-- arch/powerpc/boot/dts/fsl/p1020utm-pc.dtsi | 37 ++++++++ arch/powerpc/boot/dts/fsl/p1020utm-pc_32b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1020utm-pc_36b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc.dtsi | 37 ++++++++ arch/powerpc/boot/dts/fsl/p1021rdb-pc_32b.dts | 5 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc_36b.dts | 5 +- arch/powerpc/boot/dts/fsl/p2020rdb-pc.dtsi | 33 ++++++- 11 files changed, 251 insertions(+), 22 deletions(-)
arch/powerpc/boot/dts/fsl/p1020mbg-pc.dtsi +92 -0
@@ -83,6 +83,95 @@ compatible = "vitesse-7385"; reg = <0x2 0x0 0x20000>; }; + + cpld@3,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,p1021rdb-pc-cpld", "simple-bus", "syscon"; + reg = <0x3 0x0 0x20000>; + ranges = <0x0 0x3 0x0 0x20000>; + + watchdog@2 { + compatible = "maxim,max6370"; + reg = <0x2 0x1>; + gpios = <&gpio 11 1>; + }; + + led@8,0 { + compatible = "register-bit-led"; + reg = <0x8 0x1>; + offset = <0x8>; + mask = <0x1>; + active-low; + default-state = "keep"; + label = "status"; + function = "status"; + color = <6>; /* LED_COLOR_ID_YELLOW */ + }; + + led@9,0 { + compatible = "register-bit-led"; + reg = <0x9 0x1>; + offset = <0x9>; + mask = <0x1>; + active-low; + default-state = "keep"; + label = "fxo"; + color = <2>; /* LED_COLOR_ID_GREEN */ + }; + + led@a,0 { + compatible = "register-bit-led"; + reg = <0xa 0x1>; + offset = <0xa>; + mask = <0x1>; + active-low; + default-state = "keep"; + label = "fxs0"; + color = <2>; /* LED_COLOR_ID_GREEN */ + }; + + led@a,1 { + compatible = "register-bit-led"; + reg = <0xa 0x1>; + offset = <0xa>; + mask = <0x2>; + active-low; + default-state = "keep"; + label = "fxs1"; + color = <2>; /* LED_COLOR_ID_GREEN */ + }; + + led@a,2 { + compatible = "register-bit-led"; + reg = <0xa 0x1>; + offset = <0xa>; + mask = <0x4>; + active-low; + default-state = "keep"; + label = "fxs2"; + color = <2>; /* LED_COLOR_ID_GREEN */ + }; + + led@a,3 { + compatible = "register-bit-led"; + reg = <0xa 0x1>; + offset = <0xa>; + mask = <0x8>; + active-low; + default-state = "keep"; + label = "fxs3"; + color = <2>; /* LED_COLOR_ID_GREEN */ + }; + + reboot@d { + compatible = "syscon-reboot"; + reg = <0xd 0x1>; + offset = <0xd>; + mask = <0x1>; + value = <0x1>; + }; + }; }; &soc {
@@ -93,6 +182,9 @@ }; }; + gpio: gpio-controller@fc00 { + }; + mdio@24000 { phy0: ethernet-phy@0 { interrupts = <3 1 0 0>;
arch/powerpc/boot/dts/fsl/p1020mbg-pc_32b.dts +3 -3
@@ -44,10 +44,10 @@ lbc: localbus@ffe05000 { reg = <0x0 0xffe05000 0x0 0x1000>; - /* NOR and L2 switch */ + /* NOR, L2 switch and CPLD */ ranges = <0x0 0x0 0x0 0xec000000 0x04000000 - 0x1 0x0 0x0 0xffa00000 0x00040000 - 0x2 0x0 0x0 0xffb00000 0x00020000>; + 0x2 0x0 0x0 0xffb00000 0x00020000 + 0x3 0x0 0x0 0xffa00000 0x00040000>; }; soc: soc@ffe00000 {
arch/powerpc/boot/dts/fsl/p1020mbg-pc_36b.dts +3 -3
@@ -44,10 +44,10 @@ lbc: localbus@fffe05000 { reg = <0xf 0xffe05000 0x0 0x1000>; - /* NOR and L2 switch */ + /* NOR, L2 switch and CPLD */ ranges = <0x0 0x0 0xf 0xec000000 0x04000000 - 0x1 0x0 0xf 0xffa00000 0x00040000 - 0x2 0x0 0xf 0xffb00000 0x00020000>; + 0x2 0x0 0xf 0xffb00000 0x00020000 + 0x3 0x0 0xf 0xffa00000 0x00040000>; }; soc: soc@fffe00000 {
arch/powerpc/boot/dts/fsl/p1020rdb-pd.dts +38 -6
68 lines not on this page · raw message
arch/powerpc/boot/dts/fsl/p1020utm-pc.dtsi +37 -0
@@ -68,6 +68,40 @@ read-only; }; }; + + cpld@3,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,p1021rdb-pc-cpld", "simple-bus", "syscon"; + reg = <0x3 0x0 0x20000>; + ranges = <0x0 0x3 0x0 0x20000>; + + watchdog@2 { + compatible = "maxim,max6370"; + reg = <0x2 0x1>; + gpios = <&gpio 11 1>; + }; + + led@8,0 { + compatible = "register-bit-led"; + reg = <0x8 0x1>; + offset = <0x8>; + mask = <0x1>; + active-low; + default-state = "keep"; + label = "status"; + function = "status"; + color = <6>; /* LED_COLOR_ID_YELLOW */ + }; + + reboot@d { + compatible = "syscon-reboot"; + reg = <0xd 0x1>; + offset = <0xd>; + mask = <0x1>; + value = <0x1>; + }; + }; }; &soc {
@@ -78,6 +112,9 @@ }; }; + gpio: gpio-controller@fc00 { + }; + mdio@24000 { phy0: ethernet-phy@0 { interrupts = <3 1 0 0>;
arch/powerpc/boot/dts/fsl/p1020utm-pc_32b.dts +2 -2
@@ -46,8 +46,8 @@ /* NOR */ ranges = <0x0 0x0 0x0 0xec000000 0x02000000 - 0x1 0x0 0x0 0xffa00000 0x00040000 - 0x2 0x0 0x0 0xffb00000 0x00020000>; + 0x2 0x0 0x0 0xffb00000 0x00020000 + 0x3 0x0 0x0 0xffa00000 0x00040000>; }; soc: soc@ffe00000 {
arch/powerpc/boot/dts/fsl/p1020utm-pc_36b.dts +2 -2
@@ -46,8 +46,8 @@ /* NOR */ ranges = <0x0 0x0 0xf 0xec000000 0x02000000 - 0x1 0x0 0xf 0xffa00000 0x00040000 - 0x2 0x0 0xf 0xffb00000 0x00020000>; + 0x2 0x0 0xf 0xffb00000 0x00020000 + 0x3 0x0 0xf 0xffa00000 0x00040000>; }; soc: soc@fffe00000 {
arch/powerpc/boot/dts/fsl/p1021rdb-pc.dtsi +37 -0
@@ -136,6 +136,40 @@ compatible = "vitesse-7385"; reg = <0x2 0x0 0x20000>; }; + + cpld@3,0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "fsl,p1021rdb-pc-cpld", "simple-bus", "syscon"; + reg = <0x3 0x0 0x20000>; + ranges = <0x0 0x3 0x0 0x20000>; + + watchdog@2 { + compatible = "maxim,max6370"; + reg = <0x2 0x1>; + gpios = <&gpio 11 1>; + }; + + led@8,0 { + compatible = "register-bit-led"; + reg = <0x8 0x1>; + offset = <0x8>; + mask = <0x1>; + active-low; + default-state = "keep"; + label = "status"; + function = "status"; + color = <6>; /* LED_COLOR_ID_YELLOW */ + }; + + reboot@d { + compatible = "syscon-reboot"; + reg = <0xd 0x1>; + offset = <0xd>; + mask = <0x1>; + value = <0x1>; + }; + }; }; &soc {
@@ -187,6 +221,9 @@ }; }; + gpio: gpio-controller@fc00 { + }; + usb@22000 { phy_type = "ulpi"; };
arch/powerpc/boot/dts/fsl/p1021rdb-pc_32b.dts +3 -2
@@ -44,10 +44,11 @@ lbc: localbus@ffe05000 { reg = <0 0xffe05000 0 0x1000>; - /* NOR, NAND Flashes and Vitesse 5 port L2 switch */ + /* NOR, NAND Flashes, Vitesse 5 port L2 switch and CPLD */ ranges = <0x0 0x0 0x0 0xef000000 0x01000000 0x1 0x0 0x0 0xff800000 0x00040000 - 0x2 0x0 0x0 0xffb00000 0x00020000>; + 0x2 0x0 0x0 0xffb00000 0x00020000 + 0x3 0x0 0x0 0xffa00000 0x00020000>; }; soc: soc@ffe00000 {
arch/powerpc/boot/dts/fsl/p1021rdb-pc_36b.dts +3 -2
@@ -44,10 +44,11 @@ lbc: localbus@fffe05000 { reg = <0xf 0xffe05000 0 0x1000>; - /* NOR, NAND Flashes and Vitesse 5 port L2 switch */ + /* NOR, NAND Flashes, Vitesse 5 port L2 switch and CPLD */ ranges = <0x0 0x0 0xf 0xef000000 0x01000000 0x1 0x0 0xf 0xff800000 0x00040000 - 0x2 0x0 0xf 0xffb00000 0x00020000>; + 0x2 0x0 0xf 0xffb00000 0x00020000 + 0x3 0x0 0xf 0xffa00000 0x00020000>; }; soc: soc@fffe00000 {
arch/powerpc/boot/dts/fsl/p2020rdb-pc.dtsi +31 -2
@@ -133,9 +133,35 @@ cpld@3,0 { #address-cells = <1>; #size-cells = <1>; - compatible = "cpld"; + compatible = "fsl,p1021rdb-pc-cpld", "simple-bus", "syscon"; reg = <0x3 0x0 0x20000>; - read-only; + ranges = <0x0 0x3 0x0 0x20000>; + + watchdog@2 { + compatible = "maxim,max6370"; + reg = <0x2 0x1>; + gpios = <&gpio 11 1>; + }; + + led@8,0 { + compatible = "register-bit-led"; + reg = <0x8 0x1>; + offset = <0x8>; + mask = <0x1>; + active-low; + default-state = "keep"; + label = "status"; + function = "status"; + color = <6>; /* LED_COLOR_ID_YELLOW */ + }; + + reboot@d { + compatible = "syscon-reboot"; + reg = <0xd 0x1>; + offset = <0xd>; + mask = <0x1>; + value = <0x1>; + }; }; };
@@ -188,6 +214,9 @@ }; }; + gpio: gpio-controller@fc00 { + }; + usb@22000 { phy_type = "ulpi"; };
Signature · 1 line
2.20.1
PATCH RESEND 4/8 dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
In reply to Pali RohárAdd device-tree bindings documentation for Turris 1.x RGB LEDs.
--- .../bindings/leds/cznic,turris1x-leds.yaml | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yaml
Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yaml new file +118 -0
@@ -0,0 +1,118 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/cznic,turris1x-leds.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: CZ.NIC's Turris 1.x LEDs driver + +maintainers: + - Pali Rohár <[email protected]> + +description: + This module adds support for the RGB LEDs found on the front panel of the + Turris 1.x routers. There are 8 RGB LEDs that are controlled by CZ.NIC CPLD + firmware running on Lattice FPGA. Firmware is open source and available at + https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.v + +properties: + compatible: + const: cznic,turris1x-leds + + reg: + description: CPLD address range where LED registers are mapped + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^multi-led@[0-7]$": + type: object + $ref: leds-class-multicolor.yaml# + unevaluatedProperties: false + + properties: + reg: + minimum: 0 + maximum: 7 + + required: + - reg + +additionalProperties: false + +examples: + - | + #include <dt-bindings/leds/common.h> + + cpld@3,0 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3 0x0 0x00020000>; + + led-controller@13 { + compatible = "cznic,turris1x-leds"; + reg = <0x13 0x1d>; + #address-cells = <1>; + #size-cells = <0>; + + multi-led@0 { + reg = <0x0>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_WAN; + }; + + multi-led@1 { + reg = <0x1>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <5>; + }; + + multi-led@2 { + reg = <0x2>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <4>; + }; + + multi-led@3 { + reg = <0x3>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <3>; + }; + + multi-led@4 { + reg = <0x4>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + }; + + multi-led@5 { + reg = <0x5>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + }; + + multi-led@6 { + reg = <0x6>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_WLAN; + }; + + multi-led@7 { + reg = <0x7>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_POWER; + }; + }; + }; + +...
Signature · 1 line
2.20.1
Lee Jones
maintainerRe: [PATCH RESEND 4/8] dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
Quoted 7 lines · Pali Rohár
Add device-tree bindings documentation for Turris 1.x RGB LEDs.
Signed-off-by Pali Rohár <[email protected]>--- .../bindings/leds/cznic,turris1x-leds.yaml | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yaml
Needs a DT Ack (now Cc:ed)
Quoted 127 lines
Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yaml new file +118
-0@@ -0,0 +1,118 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/cznic,turris1x-leds.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: CZ.NIC's Turris 1.x LEDs driver + +maintainers: + - Pali Rohár <[email protected]> + +description: + This module adds support for the RGB LEDs found on the front panel of the + Turris 1.x routers. There are 8 RGB LEDs that are controlled by CZ.NIC CPLD + firmware running on Lattice FPGA. Firmware is open source and available at + https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.v + +properties: + compatible: + const: cznic,turris1x-leds + + reg: + description: CPLD address range where LED registers are mapped + maxItems: 1 + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^multi-led@[0-7]$": + type: object + $ref: leds-class-multicolor.yaml# + unevaluatedProperties: false + + properties: + reg: + minimum: 0 + maximum: 7 + + required: + - reg + +additionalProperties: false + +examples: + - | + #include <dt-bindings/leds/common.h> + + cpld@3,0 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x3 0x0 0x00020000>; + + led-controller@13 { + compatible = "cznic,turris1x-leds"; + reg = <0x13 0x1d>; + #address-cells = <1>; + #size-cells = <0>; + + multi-led@0 { + reg = <0x0>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_WAN; + }; + + multi-led@1 { + reg = <0x1>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <5>; + }; + + multi-led@2 { + reg = <0x2>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <4>; + }; + + multi-led@3 { + reg = <0x3>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <3>; + }; + + multi-led@4 { + reg = <0x4>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + }; + + multi-led@5 { + reg = <0x5>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + }; + + multi-led@6 { + reg = <0x6>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_WLAN; + }; + + multi-led@7 { + reg = <0x7>; + color = <LED_COLOR_ID_RGB>; + function = LED_FUNCTION_POWER; + }; + }; + }; + +...Signature · 1 line
2.20.1
Signature · 1 line
Lee Jones [李琼斯]
Re: [PATCH RESEND 4/8] dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
Quoted 11 lines · Lee Jones
Quoted 7 lines · Pali Rohár
Add device-tree bindings documentation for Turris 1.x RGB LEDs.
Signed-off-by Pali Rohár <[email protected]>--- .../bindings/leds/cznic,turris1x-leds.yaml | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yamlNeeds a DT Ack (now Cc:ed)
Within the same day of posting v2 of this - just after 4 hours, Pali received review and I pointed issue to address.
The issue was not addressed, just ignored.
Therefore this patch shall not be taken, until the issues are resolved or discussion is finished if there is disagreement about my comments..
Best regards,
Krzysztof
Lee Jones
maintainerRe: [PATCH RESEND 4/8] dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
Quoted 13 lines · Krzysztof Kozlowski
Quoted 11 lines · Lee Jones
Quoted 7 lines · Pali Rohár
Add device-tree bindings documentation for Turris 1.x RGB LEDs.
Signed-off-by Pali Rohár <[email protected]>--- .../bindings/leds/cznic,turris1x-leds.yaml | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yamlNeeds a DT Ack (now Cc:ed)
Quoted 7 lines
Within the same day of posting v2 of this - just after 4 hours, Pali received review and I pointed issue to address.
The issue was not addressed, just ignored.
Therefore this patch shall not be taken, until the issues are resolved or discussion is finished if there is disagreement about my comments..
Understood. Thanks for the clarification.
Signature · 1 line
Lee Jones [李琼斯]
Re: [PATCH RESEND 4/8] dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
Quoted 18 lines · On Friday 24 February 2023 09:38:37 Lee Jones wrote:
Quoted 16 lines · Krzysztof Kozlowski
Quoted 11 lines · Lee Jones
Quoted 7 lines · Pali Rohár
Add device-tree bindings documentation for Turris 1.x RGB LEDs.
Signed-off-by Pali Rohár <[email protected]>--- .../bindings/leds/cznic,turris1x-leds.yaml | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yamlNeeds a DT Ack (now Cc:ed)
Within the same day of posting v2 of this - just after 4 hours, Pali received review and I pointed issue to address.
Quoted 6 lines
Quoted 4 lines
The issue was not addressed, just ignored.
Therefore this patch shall not be taken, until the issues are resolved or discussion is finished if there is disagreement about my comments..
Understood. Thanks for the clarification.
Sorry, but this discussion was ignored by the reviewer, not by me. I have replied to all points. In other cases I have sent other emails and result was same.
I'm not going to write and send emails or pull requests or other code to people who do not want to read them or think that it is me who is ignoring even it is false information.
Re: [PATCH RESEND 4/8] dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
Quoted 26 lines · Pali Rohár
Quoted 18 lines · On Friday 24 February 2023 09:38:37 Lee Jones wrote:
Quoted 16 lines · Krzysztof Kozlowski
Quoted 11 lines · Lee Jones
Quoted 7 lines · Pali Rohár
Add device-tree bindings documentation for Turris 1.x RGB LEDs.
Signed-off-by Pali Rohár <[email protected]>--- .../bindings/leds/cznic,turris1x-leds.yaml | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yamlNeeds a DT Ack (now Cc:ed)
Within the same day of posting v2 of this - just after 4 hours, Pali received review and I pointed issue to address.
Quoted 6 lines
Quoted 4 lines
The issue was not addressed, just ignored.
Therefore this patch shall not be taken, until the issues are resolved or discussion is finished if there is disagreement about my comments..
Understood. Thanks for the clarification.
Quoted 7 lines
Sorry, but this discussion was ignored by the reviewer, not by me. I have replied to all points. In other cases I have sent other emails and result was same.
I'm not going to write and send emails or pull requests or other code to people who do not want to read them or think that it is me who is ignoring even it is false information.
Why did you trim the reply list from few folks and from me, even though discussion is about review between you and me? You had to do it deliberately, so I wonder why?
OK, you claim this is false information.
This is the last feedback from me:
https://lore.kernel.org/all/[email protected]/
Where did you respond to this feedback? Point me to the message which responds to my review comment about messed indentation?
Best regards,
Krzysztof
Re: [PATCH RESEND 4/8] dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
In reply to Pali RohárQuoted 6 lines · Pali Rohár
Add device-tree bindings documentation for Turris 1.x RGB LEDs.
Signed-off-by Pali Rohár <[email protected]>--- .../bindings/leds/cznic,turris1x-leds.yaml | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+)
NAK, because:
1. You received comments for this to fix which you ignored:
https://lore.kernel.org/all/[email protected]/
Implement the feedback you got.
2. You sent it now - without changes, ignoring feedback - not cc'ing DT maintainers.
Best regards,
Krzysztof
PATCH RESEND 5/8 leds: Add support for Turris 1.x LEDs
In reply to Pali RohárThis adds support for the RGB LEDs found on the front panel of the Turris 1.x routers. There are 8 RGB LEDs that are controlled by CZ.NIC CPLD firmware running on Lattice FPGA.
CPLD firmware provides HW triggering mode for all LEDs except WiFi LED which is automatically enabled after power on reset. LAN LEDs share HW registers for RGB colors settings, so it is not possible to set different colors for individual LAN LEDs.
CZ.NIC CPLD firmware is open source and available at:
https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.v
This driver uses the multicolor LED framework and HW led triggers.
--- .../testing/sysfs-class-led-driver-turris1x | 31 ++ drivers/leds/Kconfig | 9 + drivers/leds/Makefile | 1 + drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ 4 files changed, 515 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-led-driver-turris1x create mode 100644 drivers/leds/leds-turris-1x.c
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +31 -0
@@ -0,0 +1,31 @@ +What: /sys/class/leds/<led>/device/brightness +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) On the back size of the Turris 1.x routers there is also + a button which can be used to control the intensity of all the + LEDs at once, so that if they are too bright, user can dim them. + + The CPLD firmware cycles between 8 levels of this global + brightness, but this setting can have any integer value between + 0 and 255. It is therefore convenient to be able to change this + setting from software. + + Format: %u + +What: /sys/class/leds/<led>/device/brightness_level +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Current brightness level value (0-7). + + Format: %u + +What: /sys/class/leds/<led>/device/brightness_values +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Values of all 8 levels between which CPLD firmware cycles + when brightness button is pressed. + + Format: %u %u %u %u %u %u %u %u
drivers/leds/Kconfig +9 -0
@@ -157,6 +157,15 @@ config LEDS_EL15203000 To compile this driver as a module, choose M here: the module will be called leds-el15203000. +config LEDS_TURRIS_1X + tristate "LED support for CZ.NIC's Turris 1.x" + depends on LEDS_CLASS_MULTICOLOR + depends on OF + select LEDS_TRIGGERS + help + This option enables support for LEDs found on the front side of + CZ.NIC's Turris 1.x routers. + config LEDS_TURRIS_OMNIA tristate "LED support for CZ.NIC's Turris Omnia" depends on LEDS_CLASS_MULTICOLOR
drivers/leds/Makefile +1 -0
@@ -82,6 +82,7 @@ obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o obj-$(CONFIG_LEDS_TLC591XX) += leds-tlc591xx.o obj-$(CONFIG_LEDS_TPS6105X) += leds-tps6105x.o +obj-$(CONFIG_LEDS_TURRIS_1X) += leds-turris-1x.o obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds-turris-omnia.o obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
drivers/leds/leds-turris-1x.c new file +474 -0
474 lines not on this page · raw message
Signature · 1 line
2.20.1
Lee Jones
maintainerRe: [PATCH RESEND 5/8] leds: Add support for Turris 1.x LEDs
Pavel, are you happy with the user-space interface?
Quoted 577 lines · Pali Rohár
This adds support for the RGB LEDs found on the front panel of the Turris 1.x routers. There are 8 RGB LEDs that are controlled by CZ.NIC CPLD firmware running on Lattice FPGA.
CPLD firmware provides HW triggering mode for all LEDs except WiFi LED which is automatically enabled after power on reset. LAN LEDs share HW registers for RGB colors settings, so it is not possible to set different colors for individual LAN LEDs.
CZ.NIC CPLD firmware is open source and available at:
https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.vThis driver uses the multicolor LED framework and HW led triggers.
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Marek Behún <[email protected]>--- .../testing/sysfs-class-led-driver-turris1x | 31 ++ drivers/leds/Kconfig | 9 + drivers/leds/Makefile | 1 + drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ 4 files changed, 515 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-led-driver-turris1x create mode 100644 drivers/leds/leds-turris-1x.cDocumentation/ABI/testing/sysfs-class-led-driver-turris1x new file +31
-0@@ -0,0 +1,31 @@ +What: /sys/class/leds/<led>/device/brightness +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) On the back size of the Turris 1.x routers there is also + a button which can be used to control the intensity of all the + LEDs at once, so that if they are too bright, user can dim them. + + The CPLD firmware cycles between 8 levels of this global + brightness, but this setting can have any integer value between + 0 and 255. It is therefore convenient to be able to change this + setting from software. + + Format: %u + +What: /sys/class/leds/<led>/device/brightness_level +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Current brightness level value (0-7). + + Format: %u + +What: /sys/class/leds/<led>/device/brightness_values +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Values of all 8 levels between which CPLD firmware cycles + when brightness button is pressed. + + Format: %u %u %u %u %u %u %u %udrivers/leds/Kconfig +9
-0@@ -157,6 +157,15 @@ config LEDS_EL15203000 To compile this driver as a module, choose M here: the module will be called leds-el15203000. +config LEDS_TURRIS_1X + tristate "LED support for CZ.NIC's Turris 1.x" + depends on LEDS_CLASS_MULTICOLOR + depends on OF + select LEDS_TRIGGERS + help + This option enables support for LEDs found on the front side of + CZ.NIC's Turris 1.x routers. + config LEDS_TURRIS_OMNIA tristate "LED support for CZ.NIC's Turris Omnia" depends on LEDS_CLASS_MULTICOLORdrivers/leds/Makefile +1
-0@@ -82,6 +82,7 @@ obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o obj-$(CONFIG_LEDS_TLC591XX) += leds-tlc591xx.o obj-$(CONFIG_LEDS_TPS6105X) += leds-tps6105x.o +obj-$(CONFIG_LEDS_TURRIS_1X) += leds-turris-1x.o obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds-turris-omnia.o obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.odrivers/leds/leds-turris-1x.c new file +474
-0@@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0 +// (C) 2022 Pali Rohár <[email protected]> +// +// CZ.NIC's Turris 1.x LEDs driver, controlled by CPLD firmware: +// https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.v + +#include <linux/i2c.h> +#include <linux/led-class-multicolor.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include "leds.h" + +/* LED registers starts at byte 0x13 in CPLD memory map */ +#define TURRIS1X_LED_REG_OFF (reg) ((reg)-0x13) + +/* LEDs 1-5 share common register for setting brightness */ +#define TURRIS1X_LED_BRIGHTNESS_OFF (idx) ({ const u8 _idx = (idx) & 7; \ + (_idx == 0) ? 0 : \ + (_idx <= 5) ? 1 : \ + (_idx - 4); }) + +#define TURRIS1X_LED_BRIGHTNESS_REG (idx, color) TURRIS1X_LED_REG_OFF(0x13 + \ + 3 * TURRIS1X_LED_BRIGHTNESS_OFF(idx) + \ + ((color) & 3)) +#define TURRIS1X_LED_GLOBAL_LEVEL_REG TURRIS1X_LED_REG_OFF(0x20) +#define TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG TURRIS1X_LED_REG_OFF(0x21) +#define TURRIS1X_LED_SW_OVERRIDE_REG TURRIS1X_LED_REG_OFF(0x22) +#define TURRIS1X_LED_SW_DISABLE_REG TURRIS1X_LED_REG_OFF(0x23) +#define TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (lvl) TURRIS1X_LED_REG_OFF(0x28 + ((lvl) & 7)) + +struct turris1x_led { +struct led_classdev_mc mc_cdev; +struct mc_subled subled_info[3 ]; +u32 reg; +bool registered; +}; + +#define to_turris1x_led (l) container_of(l, struct turris1x_led, mc_cdev) + +struct turris1x_leds { +void __iomem *regs; +struct mutex lock; +struct turris1x_led leds[8 ]; +}; + +static struct led_hw_trigger_type turris1x_hw_trigger_type; + +static int turris1x_hwtrig_activate (struct led_classdev *cdev) +{ +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (lcdev_to_mccdev (cdev)); +u8 val; + +/* Disable software control of LED */ +mutex_lock (&leds->lock); + val =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val &= ~BIT (led->reg); +writeb (val, leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); +mutex_unlock (&leds->lock); + +return 0 ; +} + +static void turris1x_hwtrig_deactivate (struct led_classdev *cdev) +{ +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (lcdev_to_mccdev (cdev)); +u8 val; + +/* Enable software control of LED */ +mutex_lock (&leds->lock); + val =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val |=BIT (led->reg); +writeb (val, leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); +mutex_unlock (&leds->lock); +} + +static struct led_trigger turris1x_hw_trigger = { + .name ="turris1x-cpld" , + .activate = turris1x_hwtrig_activate, + .deactivate = turris1x_hwtrig_deactivate, + .trigger_type = &turris1x_hw_trigger_type, +}; + +static enum led_brightness turris1x_led_brightness_get (struct led_classdev *cdev) +{ +struct led_classdev_mc *mc_cdev =lcdev_to_mccdev (cdev); +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (mc_cdev); + +if (!(readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ) &BIT (led->reg))) +return 1 ; +else if (!(readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ) &BIT (led->reg))) +return 1 ; +else +return 0 ; +} + +static void turris1x_led_brightness_set (struct led_classdev *cdev, +enum led_brightness brightness) +{ +struct led_classdev_mc *mc_cdev =lcdev_to_mccdev (cdev); +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (mc_cdev); +int i, j; +u8 val; + +mutex_lock (&leds->lock); + +/* Set new brightness value for each color when LED is enabled */ +if (brightness) { +led_mc_calc_color_components (mc_cdev, brightness); +for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) +writeb (mc_cdev->subled_info[i].brightness, + leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (led->reg, i)); + +/* +* LEDs 1-5 (LAN) share common color settings in same sets +* of HW registers and therefore it is not possible to set +* different colors. So when chaning color of one LED then +* reflect color change for all of them. +*/ +if (led->reg >=1 && led->reg <=5 ) { +for (j =0 ; j <ARRAY_SIZE (leds->leds); j++) { +if (leds->leds[j].reg <1 || + leds->leds[j].reg >5 || + leds->leds[j].reg == led->reg) +continue ; +for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) + leds->leds[j].mc_cdev.subled_info[i].intensity = + mc_cdev->subled_info[i].intensity; + } + } + } + +/* Enable / disable LED for software control */ + val =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); +if (brightness && (val &BIT (led->reg))) +writeb (val & ~BIT (led->reg), + leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); +else if (!brightness && !(val &BIT (led->reg))) +writeb (val |BIT (led->reg), + leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); + +mutex_unlock (&leds->lock); +} + +static int turris1x_led_register (struct device *dev,struct turris1x_leds *leds, +struct device_node *np,u8 val_sw_override, +u8 val_sw_disable) +{ +struct led_init_data init_data = {}; +struct led_classdev *cdev; +struct turris1x_led *led; +int ret, color; +u32 reg; +int i; + +const unsigned int colors[ARRAY_SIZE (led->subled_info)] = { +LED_COLOR_ID_RED ,LED_COLOR_ID_GREEN ,LED_COLOR_ID_BLUE + }; + + ret =of_property_read_u32 (np,"reg" , ®); +if (ret || reg >=ARRAY_SIZE (leds->leds)) { +dev_err (dev, +"Node %pOF: must contain 'reg' property with values between 0 and %u\n" , + np, (unsigned int )ARRAY_SIZE (leds->leds) -1 ); +return -EINVAL ; + } + + ret =of_property_read_u32 (np,"color" , &color); +if (ret || color !=LED_COLOR_ID_RGB ) { +dev_err (dev, +"Node %pOF: must contain 'color' property with value LED_COLOR_ID_RGB\n" , + np); +return -EINVAL ; + } + + led = &leds->leds[reg]; + +if (led->registered) { +dev_err (dev,"Node %pOF: duplicate 'reg' property %u\n" , + np, reg); +return -EINVAL ; + } + + led->registered = true; + led->reg = reg; + +/* Set initial colors to what are currently in use */ +for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) { + led->subled_info[i].intensity = +readb (leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (reg, i)); + led->subled_info[i].color_index = colors[i]; + led->subled_info[i].channel = i; + } + + led->mc_cdev.subled_info = led->subled_info; + led->mc_cdev.num_colors =ARRAY_SIZE (led->subled_info); + + init_data.fwnode = &np->fwnode; + + cdev = &led->mc_cdev.led_cdev; + cdev->max_brightness =1 ; + cdev->brightness_get = turris1x_led_brightness_get; + cdev->brightness_set = turris1x_led_brightness_set; + +/* All LEDs except LED 6 (WiFi) can be controller by hardware trigger */ +if (reg !=6 ) + cdev->trigger_type = &turris1x_hw_trigger_type; + +/* Disable hardware trigger for LED 6 (WiFi) - allow software control */ +if (reg ==6 && !(val_sw_override &BIT (6 ))) { +if (!(val_sw_disable &BIT (6 ))) { + val_sw_disable |=BIT (6 ); +writeb (val_sw_disable, + leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); + } + val_sw_override |=BIT (6 ); +writeb (val_sw_override, + leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + } + +if (!(val_sw_override &BIT (reg))) + cdev->default_trigger = turris1x_hw_trigger.name; + +if (!(val_sw_override &BIT (reg)) || !(val_sw_disable &BIT (reg))) + cdev->brightness =1 ; + + ret =devm_led_classdev_multicolor_register_ext (dev, &led->mc_cdev, + &init_data); +if (ret) { +dev_err (dev,"Cannot register LED %pOF: %i\n" , np, ret); +return ret; + } + +return 0 ; +} + +static ssize_t brightness_show (struct device *dev,struct device_attribute *a, +char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int brightness; + +/* +* Current brightness value is available in read-only register +* TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG. Equivalent code is: +* level = readb(leds->regs + TURRIS1X_LED_GLOBAL_LEVEL_REG) & 7; +* brightness = readb(leds->regs + TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG(level)); +*/ + brightness =readb (leds->regs +TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG ); + +return sprintf (buf,"%u\n" , brightness); +} + +static ssize_t brightness_store (struct device *dev,struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +int best_error, error, level, value; +unsigned long brightness; +u8 best_level; + +if (kstrtoul (buf,10 , &brightness)) +return -EINVAL ; + +if (brightness >255 ) +return -EINVAL ; + +/* +* Brightness can be set only to one of 8 predefined value levels +* available in TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG(level) registers. +* Choose level which has nearest value to the specified brightness. +*/ + best_level =0 ; + best_error =INT_MAX ; +for (level =0 ; level <8 ; level++) { + value =readb (leds->regs + +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (level)); + error =abs (value - (int )brightness); +if (best_error > error) { + best_error = error; + best_level = level; + } + } + +writeb (best_level, leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ); + +return count; +} +static DEVICE_ATTR_RW (brightness); + +static ssize_t brightness_level_show (struct device *dev, +struct device_attribute *a,char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int level; + + level =readb (leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ) &7 ; + +return sprintf (buf,"%u\n" , level); +} + +static ssize_t brightness_level_store (struct device *dev, +struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned long level; + +if (kstrtoul (buf,10 , &level)) +return -EINVAL ; + +if (level >7 ) +return -EINVAL ; + +writeb (level, leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ); + +return count; +} +static DEVICE_ATTR_RW (brightness_level); + +static ssize_t brightness_values_show (struct device *dev, +struct device_attribute *a,char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int vals[8 ]; +int i; + +for (i =0 ; i <8 ; i++) + vals[i] =readb (leds->regs + +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (i)); + +return sprintf (buf,"%u %u %u %u %u %u %u %u\n" , vals[0 ], vals[1 ], + vals[2 ], vals[3 ], vals[4 ], vals[5 ], vals[6 ], vals[7 ]); +} + +static ssize_t brightness_values_store (struct device *dev, +struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int vals[8 ]; +int nchars; +int i; + +if (sscanf (buf,"%u %u %u %u %u %u %u %u%n" , &vals[0 ], &vals[1 ], + &vals[2 ], &vals[3 ], &vals[4 ], &vals[5 ], &vals[6 ], &vals[7 ], + &nchars) !=8 || nchars +1 < count) +return -EINVAL ; + +for (i =0 ; i <8 ; i++) +writeb (vals[i], + leds->regs +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (i)); + +return count; +} +static DEVICE_ATTR_RW (brightness_values); + +static struct attribute *turris1x_leds_controller_attrs[] = { + &dev_attr_brightness.attr, + &dev_attr_brightness_level.attr, + &dev_attr_brightness_values.attr, +NULL , +}; +ATTRIBUTE_GROUPS (turris1x_leds_controller); + +static int turris1x_leds_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct device_node *np =dev_of_node (dev); +struct device_node *child; +struct turris1x_leds *leds; +struct resource *res; +void __iomem *regs; +u8 val_sw_override; +u8 val_sw_disable; +int ret; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) +return -ENODEV ; + + regs =devm_ioremap_resource (dev, res); +if (IS_ERR (regs)) +return PTR_ERR (regs); + + leds =devm_kzalloc (dev,sizeof (*leds),GFP_KERNEL ); +if (!leds) +return -ENOMEM ; + +platform_set_drvdata (pdev, leds); + + leds->regs = regs; +mutex_init (&leds->lock); + + ret =devm_led_trigger_register (dev, &turris1x_hw_trigger); +if (ret) { +dev_err (dev,"Cannot register private LED trigger: %d\n" , ret); +return ret; + } + + val_sw_override =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val_sw_disable =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); + +for_each_available_child_of_node (np, child) { + ret =turris1x_led_register (dev, leds, child, + val_sw_override, val_sw_disable); +if (ret) { +of_node_put (child); +return ret; + } + } + + ret =devm_device_add_groups (dev, turris1x_leds_controller_groups); +if (ret) { +dev_err (dev,"Could not add attribute group!\n" ); +return ret; + } + +return 0 ; +} + +static void turris1x_leds_shutdown (struct platform_device *pdev) +{ +struct turris1x_leds *leds =platform_get_drvdata (pdev); +int i, j; +u8 val; + +/* +* LED registers are persisent across board resets. +* So reset LEDs to default state before kernel reboots. +*/ + +/* Disable software control of all LEDs except LED 6 (WiFi) */ +writeb (BIT (6 ), leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + +/* Turn off LED 6 (WiFi) as there is no hardware trigger for it */ + val =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); +writeb (val |BIT (6 ), leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); + +/* Reset colors of all LEDs to default values */ +for (i =0 ; i <ARRAY_SIZE (leds->leds); i++) { +/* Skip LAN2-LAN5 LEDs which share color register with LAN1 */ +if (i >=2 && i <=5 ) +continue ; +for (j =0 ; j <ARRAY_SIZE (leds->leds[i].subled_info); j++) +writeb (0xff , + leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (i, j)); + } +} + +static const struct of_device_id of_turris1x_leds_match[] = { + { .compatible ="cznic,turris1x-leds" }, + {}, +}; + +static struct platform_driver turris1x_leds_driver = { + .probe = turris1x_leds_probe, + .shutdown = turris1x_leds_shutdown, + .driver = { + .name ="turris1x_leds" , + .of_match_table = of_turris1x_leds_match, + }, +}; +module_platform_driver (turris1x_leds_driver); + +MODULE_AUTHOR ("Pali Rohár <[email protected]>" ); +MODULE_DESCRIPTION ("CZ.NIC's Turris 1.x LEDs" ); +MODULE_LICENSE ("GPL" ); +MODULE_ALIAS ("platform:turris1x_leds" );Signature · 1 line
2.20.1
Signature · 1 line
Lee Jones [李琼斯]
Re: [PATCH RESEND 5/8] leds: Add support for Turris 1.x LEDs
This interface was designed from existing turris-omnia interface:
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia
Quoted 66 lines · On Friday 27 January 2023 11:20:35 Lee Jones wrote:
Pavel, are you happy with the user-space interface?
Quoted 62 lines · Pali Rohár
This adds support for the RGB LEDs found on the front panel of the Turris 1.x routers. There are 8 RGB LEDs that are controlled by CZ.NIC CPLD firmware running on Lattice FPGA.
CPLD firmware provides HW triggering mode for all LEDs except WiFi LED which is automatically enabled after power on reset. LAN LEDs share HW registers for RGB colors settings, so it is not possible to set different colors for individual LAN LEDs.
CZ.NIC CPLD firmware is open source and available at:
https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.vThis driver uses the multicolor LED framework and HW led triggers.
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Marek Behún <[email protected]>--- .../testing/sysfs-class-led-driver-turris1x | 31 ++ drivers/leds/Kconfig | 9 + drivers/leds/Makefile | 1 + drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ 4 files changed, 515 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-led-driver-turris1x create mode 100644 drivers/leds/leds-turris-1x.cDocumentation/ABI/testing/sysfs-class-led-driver-turris1x new file +31
-0@@ -0,0 +1,31 @@ +What: /sys/class/leds/<led>/device/brightness +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) On the back size of the Turris 1.x routers there is also + a button which can be used to control the intensity of all the + LEDs at once, so that if they are too bright, user can dim them. + + The CPLD firmware cycles between 8 levels of this global + brightness, but this setting can have any integer value between + 0 and 255. It is therefore convenient to be able to change this + setting from software. + + Format: %u + +What: /sys/class/leds/<led>/device/brightness_level +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Current brightness level value (0-7). + + Format: %u + +What: /sys/class/leds/<led>/device/brightness_values +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Values of all 8 levels between which CPLD firmware cycles + when brightness button is pressed. + + Format: %u %u %u %u %u %u %u %u
Re: [PATCH RESEND 5/8] leds: Add support for Turris 1.x LEDs
In reply to Lee JonesQuoted 2 lines · Lee Jones
Pavel, are you happy with the user-space interface?
Although not about user-space but about code - entire review was ignored by Pali and not implemented:
https://lore.kernel.org/all/CAHp75Vcr6o2rm+T6Tr8sS4VXCLVHtmLPWy-njOKAvO4AcZoW=A@mail.gmail.com/
Best regards,
Krzysztof
Lee Jones
maintainerRe: [PATCH RESEND 5/8] leds: Add support for Turris 1.x LEDs
Quoted 7 lines · Krzysztof Kozlowski
Quoted 2 lines · Lee Jones
Pavel, are you happy with the user-space interface?
Although not about user-space but about code - entire review was ignored by Pali and not implemented:
https://lore.kernel.org/all/CAHp75Vcr6o2rm+T6Tr8sS4VXCLVHtmLPWy-njOKAvO4AcZoW=A@mail.gmail.com/
I just submitted a review too. Lots to work on.
Signature · 1 line
Lee Jones [李琼斯]
Re: [PATCH RESEND 5/8] leds: Add support for Turris 1.x LEDs
In reply to Pali RohárQuoted 9 lines · Pali Rohár
This adds support for the RGB LEDs found on the front panel of the Turris 1.x routers. There are 8 RGB LEDs that are controlled by CZ.NIC CPLD firmware running on Lattice FPGA.
CPLD firmware provides HW triggering mode for all LEDs except WiFi LED which is automatically enabled after power on reset. LAN LEDs share HW registers for RGB colors settings, so it is not possible to set different colors for individual LAN LEDs.
Quoted 8 lines
CZ.NIC CPLD firmware is open source and available at:
https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.vThis driver uses the multicolor LED framework and HW led triggers.
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Marek Behún <[email protected]>---
+Cc Andy, Lee, Pavel,
It looks like entire review of Andy was ignored and you just resent the same version without fixing anything.
https://lore.kernel.org/all/CAHp75Vcr6o2rm+T6Tr8sS4VXCLVHtmLPWy-njOKAvO4AcZoW=A@mail.gmail.com/
Your cover letter statement:
" list for a long time without any future movement." is so not true.
You got reviews from me for other bits, you got reviews from Andy. All these you ignored and did not send a corrected version.
This is not how the process looks like. If you receive the feedback, either you implement it or you keep discussion going (if you do not agree, for example).
Ignoring the feedback and sending the same version bypassing reviewers is unacceptable.
Best regards,
Krzysztof
Lee Jones
maintainerRe: [PATCH RESEND 5/8] leds: Add support for Turris 1.x LEDs
In reply to Pali RohárQuoted 31 lines · Pali Rohár
This adds support for the RGB LEDs found on the front panel of the Turris 1.x routers. There are 8 RGB LEDs that are controlled by CZ.NIC CPLD firmware running on Lattice FPGA.
CPLD firmware provides HW triggering mode for all LEDs except WiFi LED which is automatically enabled after power on reset. LAN LEDs share HW registers for RGB colors settings, so it is not possible to set different colors for individual LAN LEDs.
CZ.NIC CPLD firmware is open source and available at:
https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.vThis driver uses the multicolor LED framework and HW led triggers.
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Marek Behún <[email protected]>--- .../testing/sysfs-class-led-driver-turris1x | 31 ++ drivers/leds/Kconfig | 9 + drivers/leds/Makefile | 1 + drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ 4 files changed, 515 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-led-driver-turris1x create mode 100644 drivers/leds/leds-turris-1x.cDocumentation/ABI/testing/sysfs-class-led-driver-turris1x new file +0
-0
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 3
Quoted 3 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +3
-0@@ -0,0 +1,31 @@ +What: /sys/class/leds/<led>/device/brightness +Date: July 2022 +KernelVersion: 6.3
Date doesn't match the kernel version.
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 5
Quoted 2 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +2
-0+Contact: Pali Rohár <[email protected]> +Description: (RW) On the back size of the Turris 1.x routers there is also
"side"
Drop "also"
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 7
Quoted 2 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +2
-0+ a button which can be used to control the intensity of all the + LEDs at once, so that if they are too bright, user can dim them.
"the user"
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 9
Quoted 1 line
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +1
-0+ The CPLD firmware cycles between 8 levels of this global
Drop "this"
Quoted 5 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +5
-0+ brightness, but this setting can have any integer value between + 0 and 255. It is therefore convenient to be able to change this + setting from software. + + Format: %u
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 24
Quoted 10 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +10
-0+ +What: /sys/class/leds/<led>/device/brightness_level +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Current brightness level value (0-7). + + Format: %u + +What: /sys/class/leds/<led>/device/brightness_values
brightness_level_values?
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 31
Quoted 7 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +7
-0+Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Values of all 8 levels between which CPLD firmware cycles + when brightness button is pressed. + + Format: %u %u %u %u %u %u %u %u
One value per file please.
As Greg says, userspace should not have to 'parse' sysfs file output.
drivers/leds/Kconfig config LEDS_EL15203000 · line 161
Quoted 10 lines
drivers/leds/Kconfig +2
-0@@ -157,6 +157,15 @@ config LEDS_EL15203000 To compile this driver as a module, choose M here: the module will be called leds-el15203000. +config LEDS_TURRIS_1X + tristate "LED support for CZ.NIC's Turris 1.x"
Worth specifying that this is a router here?
Quoted 34 lines
drivers/leds/Kconfig +7
-0+ depends on LEDS_CLASS_MULTICOLOR + depends on OF + select LEDS_TRIGGERS + help + This option enables support for LEDs found on the front side of + CZ.NIC's Turris 1.x routers. + config LEDS_TURRIS_OMNIA tristate "LED support for CZ.NIC's Turris Omnia" depends on LEDS_CLASS_MULTICOLORdrivers/leds/Makefile +1
-0@@ -82,6 +82,7 @@ obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o obj-$(CONFIG_LEDS_TLC591XX) += leds-tlc591xx.o obj-$(CONFIG_LEDS_TPS6105X) += leds-tps6105x.o +obj-$(CONFIG_LEDS_TURRIS_1X) += leds-turris-1x.o obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds-turris-omnia.o obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.odrivers/leds/leds-turris-1x.c new file +6
-0@@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0 +// (C) 2022 Pali Rohár <[email protected]> +// +// CZ.NIC's Turris 1.x LEDs driver, controlled by CPLD firmware: +// https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.v +
drivers/leds/leds-turris-1x.c line 16
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+#include <linux/i2c.h> +#include <linux/led-class-multicolor.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include "leds.h" + +/* LED registers starts at byte 0x13 in CPLD memory map */ +#define TURRIS1X_LED_REG_OFF (reg) ((reg)-0x13)
Spaces around the "-" please.
Why not just give the registers their correct value?
Or are they already adjusted in the datasheet?
drivers/leds/leds-turris-1x.c line 26
Quoted 9 lines
drivers/leds/leds-turris-1x.c new file +9
-0+/* LEDs 1-5 share common register for setting brightness */ +#define TURRIS1X_LED_BRIGHTNESS_OFF (idx) ({ const u8 _idx = (idx) & 7; \ + (_idx == 0) ? 0 : \ + (_idx <= 5) ? 1 : \ + (_idx - 4); }) + +#define TURRIS1X_LED_BRIGHTNESS_REG (idx, color) TURRIS1X_LED_REG_OFF(0x13 + \ + 3 * TURRIS1X_LED_BRIGHTNESS_OFF(idx) + \ + ((color) & 3))
These 2 MACROs are making my head hurt. Please find a cleaner way to represent this logic, even at the expense of a few extra lines / defines.
drivers/leds/leds-turris-1x.c line 35
Quoted 9 lines
drivers/leds/leds-turris-1x.c new file +9
-0+#define TURRIS1X_LED_GLOBAL_LEVEL_REG TURRIS1X_LED_REG_OFF(0x20) +#define TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG TURRIS1X_LED_REG_OFF(0x21) +#define TURRIS1X_LED_SW_OVERRIDE_REG TURRIS1X_LED_REG_OFF(0x22) +#define TURRIS1X_LED_SW_DISABLE_REG TURRIS1X_LED_REG_OFF(0x23) +#define TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (lvl) TURRIS1X_LED_REG_OFF(0x28 + ((lvl) & 7)) + +struct turris1x_led { +struct led_classdev_mc mc_cdev; +struct mc_subled subled_info[3 ];
Please define the '3' then use that definition throughout instead of ARRAY_SIZE().
drivers/leds/leds-turris-1x.c line 40
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+u32 reg; +bool registered; +}; + +#define to_turris1x_led (l) container_of(l, struct turris1x_led, mc_cdev)
Since cdev is always available at the call-site, you can save yourself a few lines and some in-function complexity with:
#define to_turris1x_led(cdev) container_of(lcdev_to_mccdev(cdev), struct turris1x_led, mc_cdev)
drivers/leds/leds-turris-1x.c line 45
Quoted 4 lines
drivers/leds/leds-turris-1x.c new file +4
-0+struct turris1x_leds { +void __iomem *regs; +struct mutex lock; +struct turris1x_led leds[8 ];
As above s/3/8/.
drivers/leds/leds-turris-1x.c line 48
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+}; + +static struct led_hw_trigger_type turris1x_hw_trigger_type;
Why do you need a global copy of this? What's preventing you from allocating and freeing memory for it like we usually do?
drivers/leds/leds-turris-1x.c line 56
Quoted 7 lines
drivers/leds/leds-turris-1x.c new file +7
-0+static int turris1x_hwtrig_activate (struct led_classdev *cdev) +{ +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (lcdev_to_mccdev (cdev)); +u8 val; + +/* Disable software control of LED */
"Disable LED software control"
or
"of the LED"
Same in *_deactivate()
Quoted 23 lines
drivers/leds/leds-turris-1x.c new file +23
-0+mutex_lock (&leds->lock); + val =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val &= ~BIT (led->reg); +writeb (val, leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); +mutex_unlock (&leds->lock); + +return 0 ; +} + +static void turris1x_hwtrig_deactivate (struct led_classdev *cdev) +{ +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (lcdev_to_mccdev (cdev)); +u8 val; + +/* Enable software control of LED */ +mutex_lock (&leds->lock); + val =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val |=BIT (led->reg); +writeb (val, leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); +mutex_unlock (&leds->lock); +} +
drivers/leds/leds-turris-1x.c line 89
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+static struct led_trigger turris1x_hw_trigger = { + .name ="turris1x-cpld" , + .activate = turris1x_hwtrig_activate, + .deactivate = turris1x_hwtrig_deactivate, + .trigger_type = &turris1x_hw_trigger_type, +}; + +static enum led_brightness turris1x_led_brightness_get (struct led_classdev *cdev) +{ +struct led_classdev_mc *mc_cdev =lcdev_to_mccdev (cdev);
With the suggested change above, you can rid this line.
drivers/leds/leds-turris-1x.c line 94
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (mc_cdev); + +if (!(readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ) &BIT (led->reg))) +return 1 ;
That's not an enum. That's an int.
"LED_ON"
drivers/leds/leds-turris-1x.c line 98
Quoted 4 lines
drivers/leds/leds-turris-1x.c new file +4
-0+else if (!(readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ) &BIT (led->reg))) +return 1 ; +else +return 0 ;
"LED_OFF"
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+} + +static void turris1x_led_brightness_set (struct led_classdev *cdev, +enum led_brightness brightness) +{
drivers/leds/leds-turris-1x.c line 113
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+struct led_classdev_mc *mc_cdev =lcdev_to_mccdev (cdev); +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (mc_cdev); +int i, j; +u8 val; + +mutex_lock (&leds->lock); + +/* Set new brightness value for each color when LED is enabled */ +if (brightness) {
if (!brightness)
goto skip_brightness;
drivers/leds/leds-turris-1x.c line 114
Quoted 1 line
drivers/leds/leds-turris-1x.c new file +1
-0+led_mc_calc_color_components (mc_cdev, brightness);
'\n'
drivers/leds/leds-turris-1x.c line 117
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) +writeb (mc_cdev->subled_info[i].brightness, + leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (led->reg, i));
Seeing as you always add leds->regs to this, why not incorporate it into the macro and save yourself these long lines that need to be wrapped.
Also consider using holding variables to achieve the same goal.
Think about the readability and maintainability of your code.
drivers/leds/leds-turris-1x.c line 124
Quoted 7 lines
drivers/leds/leds-turris-1x.c new file +7
-0+ +/* +* LEDs 1-5 (LAN) share common color settings in same sets +* of HW registers and therefore it is not possible to set +* different colors. So when chaning color of one LED then +* reflect color change for all of them. +*/
Spell check.
drivers/leds/leds-turris-1x.c line 130
Quoted 6 lines
drivers/leds/leds-turris-1x.c new file +6
-0+if (led->reg >=1 && led->reg <=5 ) { +for (j =0 ; j <ARRAY_SIZE (leds->leds); j++) { +if (leds->leds[j].reg <1 || + leds->leds[j].reg >5 || + leds->leds[j].reg == led->reg) +continue ;
'\n'
drivers/leds/leds-turris-1x.c line 133
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) + leds->leds[j].mc_cdev.subled_info[i].intensity = + mc_cdev->subled_info[i].intensity;
What's the difference between the two 'mc_cdev's here?
drivers/leds/leds-turris-1x.c line 142
Quoted 9 lines
drivers/leds/leds-turris-1x.c new file +9
-0+ } + } + } + +/* Enable / disable LED for software control */ + val =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); +if (brightness && (val &BIT (led->reg))) +writeb (val & ~BIT (led->reg), + leds->regs +TURRIS1X_LED_SW_DISABLE_REG );
Single line.
drivers/leds/leds-turris-1x.c line 145
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+else if (!brightness && !(val &BIT (led->reg))) +writeb (val |BIT (led->reg), + leds->regs +TURRIS1X_LED_SW_DISABLE_REG );
Single line.
Quoted 12 lines
drivers/leds/leds-turris-1x.c new file +12
-0+mutex_unlock (&leds->lock); +} + +static int turris1x_led_register (struct device *dev,struct turris1x_leds *leds, +struct device_node *np,u8 val_sw_override, +u8 val_sw_disable) +{ +struct led_init_data init_data = {}; +struct led_classdev *cdev; +struct turris1x_led *led; +int ret, color; +u32 reg;
drivers/leds/leds-turris-1x.c line 168
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+int i; + +const unsigned int colors[ARRAY_SIZE (led->subled_info)] = { +LED_COLOR_ID_RED ,LED_COLOR_ID_GREEN ,LED_COLOR_ID_BLUE + }; + + ret =of_property_read_u32 (np,"reg" , ®); +if (ret || reg >=ARRAY_SIZE (leds->leds)) { + dev_err(dev, + "Node %pOF: must contain 'reg' property with values between 0 and %u\n",
IMHO this is too verbose. This is a message for an engineer who will know how to use grep and perform basic debugging.
"Invalid or missing 'reg' property" should clean this line up.
drivers/leds/leds-turris-1x.c line 176
Quoted 8 lines
drivers/leds/leds-turris-1x.c new file +8
-0+ np, (unsigned int)ARRAY_SIZE(leds->leds) - 1); +return -EINVAL ; + } + + ret =of_property_read_u32 (np,"color" , &color); +if (ret || color !=LED_COLOR_ID_RGB ) { + dev_err(dev, + "Node %pOF: must contain 'color' property with value LED_COLOR_ID_RGB\n",
As above. Keep it simple and brief.
drivers/leds/leds-turris-1x.c line 185
Quoted 9 lines
drivers/leds/leds-turris-1x.c new file +9
-0+ np); +return -EINVAL ; + } + + led = &leds->leds[reg]; + +if (led->registered) { +dev_err (dev,"Node %pOF: duplicate 'reg' property %u\n" , + np, reg);
"LED %d already registered", reg
Line wrap at 100 chars please.
drivers/leds/leds-turris-1x.c line 192
Quoted 7 lines
drivers/leds/leds-turris-1x.c new file +7
-0+return -EINVAL ; + } + + led->registered = true; + led->reg = reg; + +/* Set initial colors to what are currently in use */
"to those currently"
drivers/leds/leds-turris-1x.c line 197
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) { + led->subled_info[i].intensity = +readb (leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (reg, i)); + led->subled_info[i].color_index = colors[i]; + led->subled_info[i].channel = i;
For my own understanding, what's the difference between reg and channel?
drivers/leds/leds-turris-1x.c line 200
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+ } + + led->mc_cdev.subled_info = led->subled_info;
Why do we need 2 copies of the same info?
drivers/leds/leds-turris-1x.c line 201
Quoted 1 line
drivers/leds/leds-turris-1x.c new file +1
-0+ led->mc_cdev.num_colors =ARRAY_SIZE (led->subled_info);
This is always 3 - use a define instead.
Quoted 4 lines
drivers/leds/leds-turris-1x.c new file +4
-0+ init_data.fwnode = &np->fwnode; + + cdev = &led->mc_cdev.led_cdev; + cdev->max_brightness =1 ;
drivers/leds/leds-turris-1x.c line 216
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+ cdev->brightness_get = turris1x_led_brightness_get; + cdev->brightness_set = turris1x_led_brightness_set; + +/* All LEDs except LED 6 (WiFi) can be controller by hardware trigger */ +if (reg !=6 ) + cdev->trigger_type = &turris1x_hw_trigger_type; + +/* Disable hardware trigger for LED 6 (WiFi) - allow software control */ +if (reg ==6 && !(val_sw_override &BIT (6 ))) { +if (!(val_sw_disable &BIT (6 ))) {
Wouldn't it make things much easier if we just did it anyway (see below)?
drivers/leds/leds-turris-1x.c line 219
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+ val_sw_disable |=BIT (6 ); +writeb (val_sw_disable, + leds->regs +TURRIS1X_LED_SW_DISABLE_REG );
Wrap at 100 everywhere please.
drivers/leds/leds-turris-1x.c line 224
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+ } + val_sw_override |=BIT (6 ); +writeb (val_sw_override, + leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + }
if (reg == 6 && !(val_sw_override & BIT(6))) {
writeb(val_sw_disable, leds->regs + TURRIS1X_LED_SW_DISABLE_REG);
writeb(val_sw_override, leds->regs + TURRIS1X_LED_SW_OVERRIDE_REG);
val_sw_disable |= BIT(6);
val_sw_override |= BIT(6);
}Quoted 154 lines
drivers/leds/leds-turris-1x.c new file +154
-0+if (!(val_sw_override &BIT (reg))) + cdev->default_trigger = turris1x_hw_trigger.name; + +if (!(val_sw_override &BIT (reg)) || !(val_sw_disable &BIT (reg))) + cdev->brightness =1 ; + + ret =devm_led_classdev_multicolor_register_ext (dev, &led->mc_cdev, + &init_data); +if (ret) { +dev_err (dev,"Cannot register LED %pOF: %i\n" , np, ret); +return ret; + } + +return 0 ; +} + +static ssize_t brightness_show (struct device *dev,struct device_attribute *a, +char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int brightness; + +/* +* Current brightness value is available in read-only register +* TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG. Equivalent code is: +* level = readb(leds->regs + TURRIS1X_LED_GLOBAL_LEVEL_REG) & 7; +* brightness = readb(leds->regs + TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG(level)); +*/ + brightness =readb (leds->regs +TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG ); + +return sprintf (buf,"%u\n" , brightness); +} + +static ssize_t brightness_store (struct device *dev,struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +int best_error, error, level, value; +unsigned long brightness; +u8 best_level; + +if (kstrtoul (buf,10 , &brightness)) +return -EINVAL ; + +if (brightness >255 ) +return -EINVAL ; + +/* +* Brightness can be set only to one of 8 predefined value levels +* available in TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG(level) registers. +* Choose level which has nearest value to the specified brightness. +*/ + best_level =0 ; + best_error =INT_MAX ; +for (level =0 ; level <8 ; level++) { + value =readb (leds->regs + +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (level)); + error =abs (value - (int )brightness); +if (best_error > error) { + best_error = error; + best_level = level; + } + } + +writeb (best_level, leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ); + +return count; +} +static DEVICE_ATTR_RW (brightness); + +static ssize_t brightness_level_show (struct device *dev, +struct device_attribute *a,char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int level; + + level =readb (leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ) &7 ; + +return sprintf (buf,"%u\n" , level); +} + +static ssize_t brightness_level_store (struct device *dev, +struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned long level; + +if (kstrtoul (buf,10 , &level)) +return -EINVAL ; + +if (level >7 ) +return -EINVAL ; + +writeb (level, leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ); + +return count; +} +static DEVICE_ATTR_RW (brightness_level); + +static ssize_t brightness_values_show (struct device *dev, +struct device_attribute *a,char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int vals[8 ]; +int i; + +for (i =0 ; i <8 ; i++) + vals[i] =readb (leds->regs + +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (i)); + +return sprintf (buf,"%u %u %u %u %u %u %u %u\n" , vals[0 ], vals[1 ], + vals[2 ], vals[3 ], vals[4 ], vals[5 ], vals[6 ], vals[7 ]); +} + +static ssize_t brightness_values_store (struct device *dev, +struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int vals[8 ]; +int nchars; +int i; + +if (sscanf (buf,"%u %u %u %u %u %u %u %u%n" , &vals[0 ], &vals[1 ], + &vals[2 ], &vals[3 ], &vals[4 ], &vals[5 ], &vals[6 ], &vals[7 ], + &nchars) !=8 || nchars +1 < count) +return -EINVAL ; + +for (i =0 ; i <8 ; i++) +writeb (vals[i], + leds->regs +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (i)); + +return count; +} +static DEVICE_ATTR_RW (brightness_values); + +static struct attribute *turris1x_leds_controller_attrs[] = { + &dev_attr_brightness.attr, + &dev_attr_brightness_level.attr, + &dev_attr_brightness_values.attr, +NULL , +}; +ATTRIBUTE_GROUPS (turris1x_leds_controller); + +static int turris1x_leds_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct device_node *np =dev_of_node (dev); +struct device_node *child; +struct turris1x_leds *leds; +struct resource *res; +void __iomem *regs; +u8 val_sw_override;
drivers/leds/leds-turris-1x.c line 389
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+u8 val_sw_disable; +int ret; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) +return -ENODEV ; + + regs =devm_ioremap_resource (dev, res); +if (IS_ERR (regs)) +return PTR_ERR (regs);
devm_platform_get_and_ioremap_resource()
drivers/leds/leds-turris-1x.c line 391
Quoted 1 line
drivers/leds/leds-turris-1x.c new file +1
-0+ leds =devm_kzalloc (dev,sizeof (*leds),GFP_KERNEL );
Call this ddata everywhere.
leds->leds is not overly forthcoming.
Quoted 35 lines
drivers/leds/leds-turris-1x.c new file +35
-0+if (!leds) +return -ENOMEM ; + +platform_set_drvdata (pdev, leds); + + leds->regs = regs; +mutex_init (&leds->lock); + + ret =devm_led_trigger_register (dev, &turris1x_hw_trigger); +if (ret) { +dev_err (dev,"Cannot register private LED trigger: %d\n" , ret); +return ret; + } + + val_sw_override =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val_sw_disable =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); + +for_each_available_child_of_node (np, child) { + ret =turris1x_led_register (dev, leds, child, + val_sw_override, val_sw_disable); +if (ret) { +of_node_put (child); +return ret; + } + } + + ret =devm_device_add_groups (dev, turris1x_leds_controller_groups); +if (ret) { +dev_err (dev,"Could not add attribute group!\n" ); +return ret; + } + +return 0 ; +} +
drivers/leds/leds-turris-1x.c line 436
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+static void turris1x_leds_shutdown (struct platform_device *pdev) +{ +struct turris1x_leds *leds =platform_get_drvdata (pdev); +int i, j; +u8 val; + +/* +* LED registers are persisent across board resets. +* So reset LEDs to default state before kernel reboots. +*/
Do you really want to rely on the process before us to have done the same? Wouldn't it be better to reset on boot-up rather than shutdown?
Quoted 40 lines
drivers/leds/leds-turris-1x.c new file +37
-0+/* Disable software control of all LEDs except LED 6 (WiFi) */ +writeb (BIT (6 ), leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + +/* Turn off LED 6 (WiFi) as there is no hardware trigger for it */ + val =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); +writeb (val |BIT (6 ), leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); + +/* Reset colors of all LEDs to default values */ +for (i =0 ; i <ARRAY_SIZE (leds->leds); i++) { +/* Skip LAN2-LAN5 LEDs which share color register with LAN1 */ +if (i >=2 && i <=5 ) +continue ; +for (j =0 ; j <ARRAY_SIZE (leds->leds[i].subled_info); j++) +writeb (0xff , + leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (i, j)); + } +} + +static const struct of_device_id of_turris1x_leds_match[] = { + { .compatible ="cznic,turris1x-leds" }, + {}, +}; + +static struct platform_driver turris1x_leds_driver = { + .probe = turris1x_leds_probe, + .shutdown = turris1x_leds_shutdown, + .driver = { + .name ="turris1x_leds" , + .of_match_table = of_turris1x_leds_match, + }, +}; +module_platform_driver (turris1x_leds_driver); + +MODULE_AUTHOR ("Pali Rohár <[email protected]>" ); +MODULE_DESCRIPTION ("CZ.NIC's Turris 1.x LEDs" ); +MODULE_LICENSE ("GPL" ); +MODULE_ALIAS ("platform:turris1x_leds" );Signature · 1 line
2.20.1
Signature · 1 line
Lee Jones [李琼斯]
Re: [PATCH RESEND 5/8] leds: Add support for Turris 1.x LEDs
Quoted 145 lines · On Friday 24 February 2023 09:28:54 Lee Jones wrote:
Quoted 31 lines · Pali Rohár
This adds support for the RGB LEDs found on the front panel of the Turris 1.x routers. There are 8 RGB LEDs that are controlled by CZ.NIC CPLD firmware running on Lattice FPGA.
CPLD firmware provides HW triggering mode for all LEDs except WiFi LED which is automatically enabled after power on reset. LAN LEDs share HW registers for RGB colors settings, so it is not possible to set different colors for individual LAN LEDs.
CZ.NIC CPLD firmware is open source and available at:
https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.vThis driver uses the multicolor LED framework and HW led triggers.
Signed-off-by Pali Rohár <[email protected]>Reviewed-by Marek Behún <[email protected]>--- .../testing/sysfs-class-led-driver-turris1x | 31 ++ drivers/leds/Kconfig | 9 + drivers/leds/Makefile | 1 + drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ 4 files changed, 515 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-led-driver-turris1x create mode 100644 drivers/leds/leds-turris-1x.cDocumentation/ABI/testing/sysfs-class-led-driver-turris1x new file +0
-0Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 3
Quoted 3 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +3
-0@@ -0,0 +1,31 @@ +What: /sys/class/leds/<led>/device/brightness +Date: July 2022 +KernelVersion: 6.3Date doesn't match the kernel version.
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 5
Quoted 2 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +2
-0+Contact: Pali Rohár <[email protected]> +Description: (RW) On the back size of the Turris 1.x routers there is also"side"
Drop "also"
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 7
Quoted 2 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +2
-0+ a button which can be used to control the intensity of all the + LEDs at once, so that if they are too bright, user can dim them."the user"
Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 9
Quoted 1 line
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +1
-0+ The CPLD firmware cycles between 8 levels of this globalDrop "this"
Quoted 5 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +5
-0+ brightness, but this setting can have any integer value between + 0 and 255. It is therefore convenient to be able to change this + setting from software. + + Format: %uDocumentation/ABI/testing/sysfs-class-led-driver-turris1x line 24
Quoted 10 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +10
-0+ +What: /sys/class/leds/<led>/device/brightness_level +Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Current brightness level value (0-7). + + Format: %u + +What: /sys/class/leds/<led>/device/brightness_values
brightness_level_values?Documentation/ABI/testing/sysfs-class-led-driver-turris1x line 31
Quoted 7 lines
Documentation/ABI/testing/sysfs-class-led-driver-turris1x new file +7
-0+Date: July 2022 +KernelVersion: 6.3 +Contact: Pali Rohár <[email protected]> +Description: (RW) Values of all 8 levels between which CPLD firmware cycles + when brightness button is pressed. + + Format: %u %u %u %u %u %u %u %uOne value per file please.
As Greg says, userspace should not have to 'parse' sysfs file output.
drivers/leds/Kconfig config LEDS_EL15203000 · line 161
Quoted 10 lines
drivers/leds/Kconfig +2
-0@@ -157,6 +157,15 @@ config LEDS_EL15203000 To compile this driver as a module, choose M here: the module will be called leds-el15203000. +config LEDS_TURRIS_1X + tristate "LED support for CZ.NIC's Turris 1.x"Worth specifying that this is a router here?
Quoted 34 lines
drivers/leds/Kconfig +7
-0+ depends on LEDS_CLASS_MULTICOLOR + depends on OF + select LEDS_TRIGGERS + help + This option enables support for LEDs found on the front side of + CZ.NIC's Turris 1.x routers. + config LEDS_TURRIS_OMNIA tristate "LED support for CZ.NIC's Turris Omnia" depends on LEDS_CLASS_MULTICOLORdrivers/leds/Makefile +1
-0@@ -82,6 +82,7 @@ obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o obj-$(CONFIG_LEDS_TI_LMU_COMMON) += leds-ti-lmu-common.o obj-$(CONFIG_LEDS_TLC591XX) += leds-tlc591xx.o obj-$(CONFIG_LEDS_TPS6105X) += leds-tps6105x.o +obj-$(CONFIG_LEDS_TURRIS_1X) += leds-turris-1x.o obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds-turris-omnia.o obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.odrivers/leds/leds-turris-1x.c new file +6
-0@@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0 +// (C) 2022 Pali Rohár <[email protected]> +// +// CZ.NIC's Turris 1.x LEDs driver, controlled by CPLD firmware: +// https://gitlab.nic.cz/turris/hw/turris_cpld/-/blob/master/CZ_NIC_Router_CPLD.v +drivers/leds/leds-turris-1x.c line 16
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+#include <linux/i2c.h> +#include <linux/led-class-multicolor.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include "leds.h" + +/* LED registers starts at byte 0x13 in CPLD memory map */ +#define TURRIS1X_LED_REG_OFF (reg) ((reg)-0x13)Spaces around the "-" please.
Quoted 3 lines
Why not just give the registers their correct value?
Or are they already adjusted in the datasheet?
Yes, they are adjusted to firmware source code (and also to available documentation written from the source code).
Quoted 4 lines
Quoted 4 lines
drivers/leds/leds-turris-1x.c new file +4
-0+/* LEDs 1-5 share common register for setting brightness */ +#define TURRIS1X_LED_BRIGHTNESS_OFF (idx) ({ const u8 _idx = (idx) & 7; \ + (_idx == 0) ? 0 : \ + (_idx <= 5) ? 1 : \
Quoted 8 lines
drivers/leds/leds-turris-1x.c line 26
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+ (_idx - 4); }) + +#define TURRIS1X_LED_BRIGHTNESS_REG (idx, color) TURRIS1X_LED_REG_OFF(0x13 + \ + 3 * TURRIS1X_LED_BRIGHTNESS_OFF(idx) + \ + ((color) & 3))These 2 MACROs are making my head hurt. Please find a cleaner way to represent this logic, even at the expense of a few extra lines / defines.
I'm not sure what is the cleaner way. For me the cleaner way is to put it on one line without breaking it.
Quoted 31 lines
drivers/leds/leds-turris-1x.c line 35
Quoted 9 lines
drivers/leds/leds-turris-1x.c new file +9
-0+#define TURRIS1X_LED_GLOBAL_LEVEL_REG TURRIS1X_LED_REG_OFF(0x20) +#define TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG TURRIS1X_LED_REG_OFF(0x21) +#define TURRIS1X_LED_SW_OVERRIDE_REG TURRIS1X_LED_REG_OFF(0x22) +#define TURRIS1X_LED_SW_DISABLE_REG TURRIS1X_LED_REG_OFF(0x23) +#define TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (lvl) TURRIS1X_LED_REG_OFF(0x28 + ((lvl) & 7)) + +struct turris1x_led { +struct led_classdev_mc mc_cdev; +struct mc_subled subled_info[3 ];Please define the '3' then use that definition throughout instead of
ARRAY_SIZE().drivers/leds/leds-turris-1x.c line 40
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+u32 reg; +bool registered; +}; + +#define to_turris1x_led (l) container_of(l, struct turris1x_led, mc_cdev)Since cdev is always available at the call-site, you can save yourself a few lines and some in-function complexity with:
#define
to_turris1x_led(cdev)container_of(lcdev_to_mccdev(cdev), struct turris1x_led, mc_cdev)drivers/leds/leds-turris-1x.c line 45
Quoted 4 lines
drivers/leds/leds-turris-1x.c new file +4
-0+struct turris1x_leds { +void __iomem *regs; +struct mutex lock; +struct turris1x_led leds[8 ];As above s/3/8/.
Quoted 6 lines
drivers/leds/leds-turris-1x.c line 48
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+}; + +static struct led_hw_trigger_type turris1x_hw_trigger_type;Why do you need a global copy of this? What's preventing you from allocating and freeing memory for it like we usually do?
This is how other drivers implemented triggers.
Quoted 60 lines
drivers/leds/leds-turris-1x.c line 56
Quoted 7 lines
drivers/leds/leds-turris-1x.c new file +7
-0+static int turris1x_hwtrig_activate (struct led_classdev *cdev) +{ +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (lcdev_to_mccdev (cdev)); +u8 val; + +/* Disable software control of LED */ "Disable LED software control"
or
"of the LED"
Same in
*_deactivate()Quoted 23 lines
drivers/leds/leds-turris-1x.c new file +23
-0+mutex_lock (&leds->lock); + val =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val &= ~BIT (led->reg); +writeb (val, leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); +mutex_unlock (&leds->lock); + +return 0 ; +} + +static void turris1x_hwtrig_deactivate (struct led_classdev *cdev) +{ +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (lcdev_to_mccdev (cdev)); +u8 val; + +/* Enable software control of LED */ +mutex_lock (&leds->lock); + val =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val |=BIT (led->reg); +writeb (val, leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); +mutex_unlock (&leds->lock); +} +drivers/leds/leds-turris-1x.c line 89
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+static struct led_trigger turris1x_hw_trigger = { + .name ="turris1x-cpld" , + .activate = turris1x_hwtrig_activate, + .deactivate = turris1x_hwtrig_deactivate, + .trigger_type = &turris1x_hw_trigger_type, +}; + +static enum led_brightness turris1x_led_brightness_get (struct led_classdev *cdev) +{ +struct led_classdev_mc *mc_cdev =lcdev_to_mccdev (cdev);With the suggested change above, you can rid this line.
drivers/leds/leds-turris-1x.c line 94
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (mc_cdev); + +if (!(readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ) &BIT (led->reg))) +return 1 ;That's not an enum. That's an int.
Quoted 1 line
"
LED_ON"
In was there before but during review I was told to change LED_ON to 1. So it should be changed back to LED_ON?
Quoted 147 lines
drivers/leds/leds-turris-1x.c line 98
Quoted 4 lines
drivers/leds/leds-turris-1x.c new file +4
-0+else if (!(readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ) &BIT (led->reg))) +return 1 ; +else +return 0 ;"
LED_OFF"Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+} + +static void turris1x_led_brightness_set (struct led_classdev *cdev, +enum led_brightness brightness) +{drivers/leds/leds-turris-1x.c line 113
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+struct led_classdev_mc *mc_cdev =lcdev_to_mccdev (cdev); +struct turris1x_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct turris1x_led *led =to_turris1x_led (mc_cdev); +int i, j; +u8 val; + +mutex_lock (&leds->lock); + +/* Set new brightness value for each color when LED is enabled */ +if (brightness) {if (!brightness)
goto skip_brightness;drivers/leds/leds-turris-1x.c line 114
Quoted 1 line
drivers/leds/leds-turris-1x.c new file +1
-0+led_mc_calc_color_components (mc_cdev, brightness);'\n'
drivers/leds/leds-turris-1x.c line 117
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) +writeb (mc_cdev->subled_info[i].brightness, + leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (led->reg, i));Seeing as you always add
leds->regsto this, why not incorporate it into the macro and save yourself these long lines that need to be wrapped.Also consider using holding variables to achieve the same goal.
Think about the readability and maintainability of your code.
drivers/leds/leds-turris-1x.c line 124
Quoted 7 lines
drivers/leds/leds-turris-1x.c new file +7
-0+ +/* +* LEDs 1-5 (LAN) share common color settings in same sets +* of HW registers and therefore it is not possible to set +* different colors. So when chaning color of one LED then +* reflect color change for all of them. +*/ Spell check.
drivers/leds/leds-turris-1x.c line 130
Quoted 6 lines
drivers/leds/leds-turris-1x.c new file +6
-0+if (led->reg >=1 && led->reg <=5 ) { +for (j =0 ; j <ARRAY_SIZE (leds->leds); j++) { +if (leds->leds[j].reg <1 || + leds->leds[j].reg >5 || + leds->leds[j].reg == led->reg) +continue ;'\n'
drivers/leds/leds-turris-1x.c line 133
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) + leds->leds[j].mc_cdev.subled_info[i].intensity = + mc_cdev->subled_info[i].intensity;What's the difference between the two 'mc_cdev's here?
drivers/leds/leds-turris-1x.c line 142
Quoted 9 lines
drivers/leds/leds-turris-1x.c new file +9
-0+ } + } + } + +/* Enable / disable LED for software control */ + val =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); +if (brightness && (val &BIT (led->reg))) +writeb (val & ~BIT (led->reg), + leds->regs +TURRIS1X_LED_SW_DISABLE_REG );Single line.
drivers/leds/leds-turris-1x.c line 145
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+else if (!brightness && !(val &BIT (led->reg))) +writeb (val |BIT (led->reg), + leds->regs +TURRIS1X_LED_SW_DISABLE_REG );Single line.
Quoted 12 lines
drivers/leds/leds-turris-1x.c new file +12
-0+mutex_unlock (&leds->lock); +} + +static int turris1x_led_register (struct device *dev,struct turris1x_leds *leds, +struct device_node *np,u8 val_sw_override, +u8 val_sw_disable) +{ +struct led_init_data init_data = {}; +struct led_classdev *cdev; +struct turris1x_led *led; +int ret, color; +u32 reg;drivers/leds/leds-turris-1x.c line 168
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+int i; + +const unsigned int colors[ARRAY_SIZE (led->subled_info)] = { +LED_COLOR_ID_RED ,LED_COLOR_ID_GREEN ,LED_COLOR_ID_BLUE + }; + + ret =of_property_read_u32 (np,"reg" , ®); +if (ret || reg >=ARRAY_SIZE (leds->leds)) { + dev_err(dev, + "Node %pOF: must contain 'reg' property with values between 0 and %u\n",IMHO this is too verbose. This is a message for an engineer who will know how to use grep and perform basic debugging.
"Invalid or missing 'reg' property" should clean this line up.
drivers/leds/leds-turris-1x.c line 176
Quoted 8 lines
drivers/leds/leds-turris-1x.c new file +8
-0+ np, (unsigned int)ARRAY_SIZE(leds->leds) - 1); +return -EINVAL ; + } + + ret =of_property_read_u32 (np,"color" , &color); +if (ret || color !=LED_COLOR_ID_RGB ) { + dev_err(dev, + "Node %pOF: must contain 'color' property with value LED_COLOR_ID_RGB\n",As above. Keep it simple and brief.
drivers/leds/leds-turris-1x.c line 185
Quoted 9 lines
drivers/leds/leds-turris-1x.c new file +9
-0+ np); +return -EINVAL ; + } + + led = &leds->leds[reg]; + +if (led->registered) { +dev_err (dev,"Node %pOF: duplicate 'reg' property %u\n" , + np, reg);"LED %d already registered", reg
Line wrap at 100 chars please.
drivers/leds/leds-turris-1x.c line 192
Quoted 7 lines
drivers/leds/leds-turris-1x.c new file +7
-0+return -EINVAL ; + } + + led->registered = true; + led->reg = reg; + +/* Set initial colors to what are currently in use */ "to those currently"
Quoted 7 lines
drivers/leds/leds-turris-1x.c line 197
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+for (i =0 ; i <ARRAY_SIZE (led->subled_info); i++) { + led->subled_info[i].intensity = +readb (leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (reg, i)); + led->subled_info[i].color_index = colors[i]; + led->subled_info[i].channel = i;For my own understanding, what's the difference between reg and channel?
reg is the register which represents particular "LED" as seen by the user on the box and channel is color of that LED. Every "LED" has 3 colors which can be configured separately.
Quoted 10 lines
drivers/leds/leds-turris-1x.c line 200
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+ } + + led->mc_cdev.subled_info = led->subled_info;Why do we need 2 copies of the same info?
drivers/leds/leds-turris-1x.c line 201
Quoted 1 line
drivers/leds/leds-turris-1x.c new file +1
-0+ led->mc_cdev.num_colors =ARRAY_SIZE (led->subled_info);This is always 3 - use a define instead.
Quoted 16 lines
Quoted 4 lines
drivers/leds/leds-turris-1x.c new file +4
-0+ init_data.fwnode = &np->fwnode; + + cdev = &led->mc_cdev.led_cdev; + cdev->max_brightness =1 ;drivers/leds/leds-turris-1x.c line 216
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+ cdev->brightness_get = turris1x_led_brightness_get; + cdev->brightness_set = turris1x_led_brightness_set; + +/* All LEDs except LED 6 (WiFi) can be controller by hardware trigger */ +if (reg !=6 ) + cdev->trigger_type = &turris1x_hw_trigger_type; + +/* Disable hardware trigger for LED 6 (WiFi) - allow software control */ +if (reg ==6 && !(val_sw_override &BIT (6 ))) { +if (!(val_sw_disable &BIT (6 ))) {Wouldn't it make things much easier if we just did it anyway (see below)?
I just wanted to avoid accessing registers of the external memory device when not needed.
Quoted 232 lines
drivers/leds/leds-turris-1x.c line 219
Quoted 3 lines
drivers/leds/leds-turris-1x.c new file +3
-0+ val_sw_disable |=BIT (6 ); +writeb (val_sw_disable, + leds->regs +TURRIS1X_LED_SW_DISABLE_REG );Wrap at 100 everywhere please.
drivers/leds/leds-turris-1x.c line 224
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+ } + val_sw_override |=BIT (6 ); +writeb (val_sw_override, + leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + }if (reg == 6 && !(val_sw_override & BIT(6))) { writeb(val_sw_disable, leds->regs + TURRIS1X_LED_SW_DISABLE_REG); writeb(val_sw_override, leds->regs + TURRIS1X_LED_SW_OVERRIDE_REG); val_sw_disable |= BIT(6); val_sw_override |= BIT(6); }Quoted 154 lines
drivers/leds/leds-turris-1x.c new file +154
-0+if (!(val_sw_override &BIT (reg))) + cdev->default_trigger = turris1x_hw_trigger.name; + +if (!(val_sw_override &BIT (reg)) || !(val_sw_disable &BIT (reg))) + cdev->brightness =1 ; + + ret =devm_led_classdev_multicolor_register_ext (dev, &led->mc_cdev, + &init_data); +if (ret) { +dev_err (dev,"Cannot register LED %pOF: %i\n" , np, ret); +return ret; + } + +return 0 ; +} + +static ssize_t brightness_show (struct device *dev,struct device_attribute *a, +char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int brightness; + +/* +* Current brightness value is available in read-only register +* TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG. Equivalent code is: +* level = readb(leds->regs + TURRIS1X_LED_GLOBAL_LEVEL_REG) & 7; +* brightness = readb(leds->regs + TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG(level)); +*/ + brightness =readb (leds->regs +TURRIS1X_LED_GET_GLOBAL_BRIGHTNESS_REG ); + +return sprintf (buf,"%u\n" , brightness); +} + +static ssize_t brightness_store (struct device *dev,struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +int best_error, error, level, value; +unsigned long brightness; +u8 best_level; + +if (kstrtoul (buf,10 , &brightness)) +return -EINVAL ; + +if (brightness >255 ) +return -EINVAL ; + +/* +* Brightness can be set only to one of 8 predefined value levels +* available in TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG(level) registers. +* Choose level which has nearest value to the specified brightness. +*/ + best_level =0 ; + best_error =INT_MAX ; +for (level =0 ; level <8 ; level++) { + value =readb (leds->regs + +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (level)); + error =abs (value - (int )brightness); +if (best_error > error) { + best_error = error; + best_level = level; + } + } + +writeb (best_level, leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ); + +return count; +} +static DEVICE_ATTR_RW (brightness); + +static ssize_t brightness_level_show (struct device *dev, +struct device_attribute *a,char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int level; + + level =readb (leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ) &7 ; + +return sprintf (buf,"%u\n" , level); +} + +static ssize_t brightness_level_store (struct device *dev, +struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned long level; + +if (kstrtoul (buf,10 , &level)) +return -EINVAL ; + +if (level >7 ) +return -EINVAL ; + +writeb (level, leds->regs +TURRIS1X_LED_GLOBAL_LEVEL_REG ); + +return count; +} +static DEVICE_ATTR_RW (brightness_level); + +static ssize_t brightness_values_show (struct device *dev, +struct device_attribute *a,char *buf) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int vals[8 ]; +int i; + +for (i =0 ; i <8 ; i++) + vals[i] =readb (leds->regs + +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (i)); + +return sprintf (buf,"%u %u %u %u %u %u %u %u\n" , vals[0 ], vals[1 ], + vals[2 ], vals[3 ], vals[4 ], vals[5 ], vals[6 ], vals[7 ]); +} + +static ssize_t brightness_values_store (struct device *dev, +struct device_attribute *a, +const char *buf,size_t count) +{ +struct turris1x_leds *leds =dev_get_drvdata (dev); +unsigned int vals[8 ]; +int nchars; +int i; + +if (sscanf (buf,"%u %u %u %u %u %u %u %u%n" , &vals[0 ], &vals[1 ], + &vals[2 ], &vals[3 ], &vals[4 ], &vals[5 ], &vals[6 ], &vals[7 ], + &nchars) !=8 || nchars +1 < count) +return -EINVAL ; + +for (i =0 ; i <8 ; i++) +writeb (vals[i], + leds->regs +TURRIS1X_LED_GLOBAL_BRIGHTNESS_REG (i)); + +return count; +} +static DEVICE_ATTR_RW (brightness_values); + +static struct attribute *turris1x_leds_controller_attrs[] = { + &dev_attr_brightness.attr, + &dev_attr_brightness_level.attr, + &dev_attr_brightness_values.attr, +NULL , +}; +ATTRIBUTE_GROUPS (turris1x_leds_controller); + +static int turris1x_leds_probe (struct platform_device *pdev) +{ +struct device *dev = &pdev->dev; +struct device_node *np =dev_of_node (dev); +struct device_node *child; +struct turris1x_leds *leds; +struct resource *res; +void __iomem *regs; +u8 val_sw_override;drivers/leds/leds-turris-1x.c line 389
Quoted 10 lines
drivers/leds/leds-turris-1x.c new file +10
-0+u8 val_sw_disable; +int ret; + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) +return -ENODEV ; + + regs =devm_ioremap_resource (dev, res); +if (IS_ERR (regs)) +return PTR_ERR (regs);
devm_platform_get_and_ioremap_resource()drivers/leds/leds-turris-1x.c line 391
Quoted 1 line
drivers/leds/leds-turris-1x.c new file +1
-0+ leds =devm_kzalloc (dev,sizeof (*leds),GFP_KERNEL );Call this ddata everywhere.
leds->ledsis not overly forthcoming.Quoted 40 lines
drivers/leds/leds-turris-1x.c new file +40
-0+if (!leds) +return -ENOMEM ; + +platform_set_drvdata (pdev, leds); + + leds->regs = regs; +mutex_init (&leds->lock); + + ret =devm_led_trigger_register (dev, &turris1x_hw_trigger); +if (ret) { +dev_err (dev,"Cannot register private LED trigger: %d\n" , ret); +return ret; + } + + val_sw_override =readb (leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + val_sw_disable =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); + +for_each_available_child_of_node (np, child) { + ret =turris1x_led_register (dev, leds, child, + val_sw_override, val_sw_disable); +if (ret) { +of_node_put (child); +return ret; + } + } + + ret =devm_device_add_groups (dev, turris1x_leds_controller_groups); +if (ret) { +dev_err (dev,"Could not add attribute group!\n" ); +return ret; + } + +return 0 ; +} + +static void turris1x_leds_shutdown (struct platform_device *pdev) +{ +struct turris1x_leds *leds =platform_get_drvdata (pdev); +int i, j; +u8 val;
Quoted 8 lines
drivers/leds/leds-turris-1x.c line 436
Quoted 5 lines
drivers/leds/leds-turris-1x.c new file +5
-0+ +/* +* LED registers are persisent across board resets. +* So reset LEDs to default state before kernel reboots. +*/ Do you really want to rely on the process before us to have done the same?
Yes.
Quoted 1 line
Wouldn't it be better to reset on boot-up rather than shutdown?
No.
During board reset, firmware shows specific LED pattern which show to user that board is being reset. As stated above LED registers are persistent across board resets, so to see visualize this pattern correctly, it is needed to reset LED registers to default state before reboot.
U-Boot bootloader resets registers to defaults but obviously it is too late (as board reset at this stage finished). Also bootloader sets specific LED pattern if booting into the "recovery" / "reflashing" mode and we want to preserve this settings. This is already in the probe phase implemented.
Quoted 43 lines
Quoted 40 lines
drivers/leds/leds-turris-1x.c new file +37
-0+/* Disable software control of all LEDs except LED 6 (WiFi) */ +writeb (BIT (6 ), leds->regs +TURRIS1X_LED_SW_OVERRIDE_REG ); + +/* Turn off LED 6 (WiFi) as there is no hardware trigger for it */ + val =readb (leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); +writeb (val |BIT (6 ), leds->regs +TURRIS1X_LED_SW_DISABLE_REG ); + +/* Reset colors of all LEDs to default values */ +for (i =0 ; i <ARRAY_SIZE (leds->leds); i++) { +/* Skip LAN2-LAN5 LEDs which share color register with LAN1 */ +if (i >=2 && i <=5 ) +continue ; +for (j =0 ; j <ARRAY_SIZE (leds->leds[i].subled_info); j++) +writeb (0xff , + leds->regs +TURRIS1X_LED_BRIGHTNESS_REG (i, j)); + } +} + +static const struct of_device_id of_turris1x_leds_match[] = { + { .compatible ="cznic,turris1x-leds" }, + {}, +}; + +static struct platform_driver turris1x_leds_driver = { + .probe = turris1x_leds_probe, + .shutdown = turris1x_leds_shutdown, + .driver = { + .name ="turris1x_leds" , + .of_match_table = of_turris1x_leds_match, + }, +}; +module_platform_driver (turris1x_leds_driver); + +MODULE_AUTHOR ("Pali Rohár <[email protected]>" ); +MODULE_DESCRIPTION ("CZ.NIC's Turris 1.x LEDs" ); +MODULE_LICENSE ("GPL" ); +MODULE_ALIAS ("platform:turris1x_leds" );Signature · 1 line
2.20.1Signature · 1 line
Lee Jones [李琼斯]
PATCH RESEND 6/8 leds: turris-omnia: support HW controlled mode via private trigger
In reply to Pali RohárFrom: Marek Behún <[email protected]>
Add support for enabling MCU controlled mode of the Turris Omnia LEDs via a LED private trigger called "omnia-mcu".
When in MCU controlled mode, the user can still set LED color, but the blinking is done by MCU, which does different things for various LEDs:
- WAN LED is blinked according to the LED[0] pin of the WAN PHY
- LAN LEDs are blinked according to the LED[0] output of corresponding port of the LAN switch
- PCIe LEDs are blinked according to the logical OR of the MiniPCIe port LED pins
For a long time I wanted to actually do this differently: I wanted to make the netdev trigger to transparently offload the blinking to the HW if user set compatible settings for the netdev trigger. There was some work on this, and hopefully we will be able to complete it sometime, but since there are various complications, it will probably not be soon.
In the meantime let's support HW controlled mode via this private LED trigger. If, in the future, we manage to complete the netdev trigger offloading, we can still keep this private trigger for backwards compatibility, if needed.
We also set "omnia-mcu" to cdev->default_trigger, so that the MCU keeps control until the user first wants to take over it. If a different default trigger is specified in device-tree via the linux,default-trigger property, LED class will overwrite cdev->default_trigger, and so the DT property will be respected.
--- drivers/leds/Kconfig | 1 + drivers/leds/leds-turris-omnia.c | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+)
drivers/leds/Kconfig +1 -0
@@ -172,6 +172,7 @@ config LEDS_TURRIS_OMNIA depends on I2C depends on MACH_ARMADA_38X || COMPILE_TEST depends on OF + select LEDS_TRIGGERS help This option enables basic support for the LEDs found on the front side of CZ.NIC's Turris Omnia router. There are 12 RGB LEDs on the
drivers/leds/leds-turris-omnia.c +41 -0
59 lines not on this page · raw message
Signature · 1 line
2.20.1
Lee Jones
maintainerRe: [PATCH RESEND 6/8] leds: turris-omnia: support HW controlled mode via private trigger
Quoted 56 lines · Pali Rohár
From: Marek Behún <[email protected]>
Add support for enabling MCU controlled mode of the Turris Omnia LEDs via a LED private trigger called "omnia-mcu".
When in MCU controlled mode, the user can still set LED color, but the blinking is done by MCU, which does different things for various LEDs:
- WAN LED is blinked according to the LED[0] pin of the WAN PHY
- LAN LEDs are blinked according to the LED[0] output of corresponding port of the LAN switch
- PCIe LEDs are blinked according to the logical OR of the MiniPCIe port LED pinsFor a long time I wanted to actually do this differently: I wanted to make the netdev trigger to transparently offload the blinking to the HW if user set compatible settings for the netdev trigger. There was some work on this, and hopefully we will be able to complete it sometime, but since there are various complications, it will probably not be soon.
In the meantime let's support HW controlled mode via this private LED trigger. If, in the future, we manage to complete the netdev trigger offloading, we can still keep this private trigger for backwards compatibility, if needed.
We also set "omnia-mcu" to
cdev->default_trigger, so that the MCU keeps control until the user first wants to take over it. If a different default trigger is specified in device-tree via thelinux,default-triggerproperty, LED class will overwritecdev->default_trigger, and so the DT property will be respected.Signed-off-by Marek Behún <[email protected]>Fixes 40624346b7ae ("ARM: dts: turris-omnia: enable LED controller node")Reviewed-by Pali Rohár <[email protected]>--- drivers/leds/Kconfig | 1 + drivers/leds/leds-turris-omnia.c | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+)drivers/leds/Kconfig +1
-0@@ -172,6 +172,7 @@ config LEDS_TURRIS_OMNIA depends on I2C depends on MACH_ARMADA_38X || COMPILE_TEST depends on OF + select LEDS_TRIGGERS help This option enables basic support for the LEDs found on the front side of CZ.NIC's Turris Omnia router. There are 12 RGB LEDs on thedrivers/leds/leds-turris-omnia.c +0
-0
drivers/leds/leds-turris-omnia.c struct omnia_leds { · line 44
Quoted 4 lines
drivers/leds/leds-turris-omnia.c +1
-0@@ -41,6 +41,39 @@ struct omnia_leds {struct omnia_led leds[]; }; +static struct led_hw_trigger_type omnia_hw_trigger_type;
Really not a fan of anything global if it can be worked around.
drivers/leds/leds-turris-omnia.c struct omnia_leds { · line 48
Quoted 3 lines
drivers/leds/leds-turris-omnia.c +3
-0+static int omnia_hwtrig_activate (struct led_classdev *cdev) +{ +struct omnia_leds *leds =dev_get_drvdata (cdev->dev->parent);
Out of interest, who is the parent?
drivers/leds/leds-turris-omnia.c struct omnia_leds { · line 53
Quoted 5 lines
drivers/leds/leds-turris-omnia.c +5
-0+struct omnia_led *led =to_omnia_led (lcdev_to_mccdev (cdev)); + +/* put the LED into MCU controlled mode */ +return i2c_smbus_write_byte_data (leds->client,CMD_LED_MODE , +CMD_LED_MODE_LED (led->reg));
Wrap at 100 chars everywhere.
drivers/leds/leds-turris-omnia.c struct omnia_leds { · line 59
Quoted 6 lines
drivers/leds/leds-turris-omnia.c +6
-0+} + +static void omnia_hwtrig_deactivate (struct led_classdev *cdev) +{ +struct omnia_leds *leds =dev_get_drvdata (cdev->dev->parent); +struct omnia_led *led =to_omnia_led (lcdev_to_mccdev (cdev));
Place lcdev_to_mccdev() in to_omnia_led().
drivers/leds/leds-turris-omnia.c struct omnia_leds { · line 62
Quoted 3 lines
drivers/leds/leds-turris-omnia.c +3
-0+int ret; + +/* put the LED into software mode */
"Put"
Quoted 42 lines
drivers/leds/leds-turris-omnia.c +22
-0+ ret =i2c_smbus_write_byte_data (leds->client,CMD_LED_MODE , +CMD_LED_MODE_LED (led->reg) | +CMD_LED_MODE_USER ); +if (ret <0 ) +dev_err (cdev->dev,"Cannot put to software mode: %i\n" , ret); +} + +static struct led_trigger omnia_hw_trigger = { + .name ="omnia-mcu" , + .activate = omnia_hwtrig_activate, + .deactivate = omnia_hwtrig_deactivate, + .trigger_type = &omnia_hw_trigger_type, +}; +static int omnia_led_brightness_set_blocking (struct led_classdev *cdev,enum led_brightness brightness) {@@ -112,6 +145,8 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, cdev = &led->mc_cdev.led_cdev; cdev->max_brightness =255 ; cdev->brightness_set_blocking = omnia_led_brightness_set_blocking; + cdev->trigger_type = &omnia_hw_trigger_type; + cdev->default_trigger = omnia_hw_trigger.name;/* put the LED into software mode */ ret = i2c_smbus_write_byte_data(client, CMD_LED_MODE,@@ -228,6 +263,12 @@ static int omnia_leds_probe(struct i2c_client *client,mutex_init (&leds->lock); + ret =devm_led_trigger_register (dev, &omnia_hw_trigger); +if (ret <0 ) { +dev_err (dev,"Cannot register private LED trigger: %d\n" , ret); +return ret; + } + led = &leds->leds[0 ];for_each_available_child_of_node (np, child) { ret =omnia_led_register (client, led, child);Signature · 1 line
2.20.1
Signature · 1 line
Lee Jones [李琼斯]
PATCH RESEND 7/8 leds: turris-omnia: initialize multi-intensity to full
In reply to Pali RohárFrom: Marek Behún <[email protected]>
The default color of each LED before driver probe (255, 255, 255). Initialize multi_intensity to this value, so that it corresponds to the reality.
--- drivers/leds/leds-turris-omnia.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/leds/leds-turris-omnia.c +3 -0
@@ -131,10 +131,13 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, } led->subled_info[0 ].color_index =LED_COLOR_ID_RED ; + led->subled_info[0 ].intensity =255 ; led->subled_info[0 ].channel =0 ; led->subled_info[1 ].color_index =LED_COLOR_ID_GREEN ; + led->subled_info[1 ].intensity =255 ; led->subled_info[1 ].channel =1 ; led->subled_info[2 ].color_index =LED_COLOR_ID_BLUE ; + led->subled_info[2 ].intensity =255 ; led->subled_info[2 ].channel =2 ; led->mc_cdev.subled_info = led->subled_info;
Signature · 1 line
2.20.1
Re: [PATCH RESEND 7/8] leds: turris-omnia: initialize multi-intensity to full
Quoted 9 lines · Pali Rohár
From: Marek Behún <[email protected]>
The default color of each LED before driver probe (255, 255, 255). Initialize
multi_intensityto this value, so that it corresponds to the reality.Signed-off-by Marek Behún <[email protected]>Fixes 089381b27abe ("leds: initial support for Turris Omnia LEDs")Reviewed-by Pali Rohár <[email protected]>
Quoted 25 lines
--- drivers/leds/leds-turris-omnia.c | 3 +++ 1 file changed, 3 insertions(+)drivers/leds/leds-turris-omnia.c +3
-0@@ -131,10 +131,13 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, } led->subled_info[0 ].color_index =LED_COLOR_ID_RED ; + led->subled_info[0 ].intensity =255 ; led->subled_info[0 ].channel =0 ; led->subled_info[1 ].color_index =LED_COLOR_ID_GREEN ; + led->subled_info[1 ].intensity =255 ; led->subled_info[1 ].channel =1 ; led->subled_info[2 ].color_index =LED_COLOR_ID_BLUE ; + led->subled_info[2 ].intensity =255 ; led->subled_info[2 ].channel =2 ; led->mc_cdev.subled_info = led->subled_info;Signature · 1 line
2.20.1
Signature · 1 line
Lee Jones [李琼斯]
PATCH RESEND 8/8 leds: turris-omnia: change max brightness from 255 to 1
In reply to Pali RohárFrom: Marek Behún <[email protected]>
Using binary brightness makes more sense for this controller, because internally in the MCU it works that way: the LED has a color, and a state whether it is ON or OFF.
The resulting brightness computation with led_mc_calc_color_components() will now always result in either (0, 0, 0) or the multi_intensity value.
--- drivers/leds/leds-turris-omnia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/leds/leds-turris-omnia.c +1 -1
@@ -146,7 +146,7 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, init_data.fwnode = &np->fwnode; cdev = &led->mc_cdev.led_cdev; - cdev->max_brightness =255 ; + cdev->max_brightness =1 ; cdev->brightness_set_blocking = omnia_led_brightness_set_blocking; cdev->trigger_type = &omnia_hw_trigger_type; cdev->default_trigger = omnia_hw_trigger.name;
Signature · 1 line
2.20.1
Lee Jones
maintainerRe: [PATCH RESEND 8/8] leds: turris-omnia: change max brightness from 255 to 1
Quoted 21 lines · Pali Rohár
From: Marek Behún <[email protected]>
Using binary brightness makes more sense for this controller, because internally in the MCU it works that way: the LED has a color, and a state whether it is ON or OFF.
The resulting brightness computation with
led_mc_calc_color_components()will now always result in either (0, 0, 0) or themulti_intensityvalue.Signed-off-by Marek Behún <[email protected]>Fixes 089381b27abe ("leds: initial support for Turris Omnia LEDs")Reviewed-by Pali Rohár <[email protected]>--- drivers/leds/leds-turris-omnia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/leds/leds-turris-omnia.c +0
-0
drivers/leds/leds-turris-omnia.c static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, · line 149
Quoted 5 lines
drivers/leds/leds-turris-omnia.c +1
-1@@ -146,7 +146,7 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, init_data.fwnode = &np->fwnode; cdev = &led->mc_cdev.led_cdev; - cdev->max_brightness =255 ; + cdev->max_brightness =1 ;
Should this now be LED_ON?
Quoted 6 lines
drivers/leds/leds-turris-omnia.c +0
-0cdev->brightness_set_blocking = omnia_led_brightness_set_blocking; cdev->trigger_type = &omnia_hw_trigger_type; cdev->default_trigger = omnia_hw_trigger.name;Signature · 1 line
2.20.1
Signature · 1 line
Lee Jones [李琼斯]
Re: [PATCH RESEND 8/8] leds: turris-omnia: change max brightness from 255 to 1
Quoted 25 lines · On Friday 24 February 2023 09:34:11 Lee Jones wrote:
Quoted 23 lines · Pali Rohár
From: Marek Behún <[email protected]>
Using binary brightness makes more sense for this controller, because internally in the MCU it works that way: the LED has a color, and a state whether it is ON or OFF.
The resulting brightness computation with
led_mc_calc_color_components()will now always result in either (0, 0, 0) or themulti_intensityvalue.Signed-off-by Marek Behún <[email protected]>Fixes 089381b27abe ("leds: initial support for Turris Omnia LEDs")Reviewed-by Pali Rohár <[email protected]>--- drivers/leds/leds-turris-omnia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/leds/leds-turris-omnia.c +0
-0@@ -146,7 +146,7 @@ static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, init_data.fwnode = &np->fwnode;
Quoted 5 lines
drivers/leds/leds-turris-omnia.c static int omnia_led_register(struct i2c_client *client, struct omnia_led *led, · line 149
Quoted 3 lines
drivers/leds/leds-turris-omnia.c +1
-1cdev = &led->mc_cdev.led_cdev; - cdev->max_brightness =255 ; + cdev->max_brightness =1 ;Should this now be
LED_ON?
Somebody said that LED_ON is deprecated.
Quoted 9 lines
Quoted 6 lines
drivers/leds/leds-turris-omnia.c +0
-0cdev->brightness_set_blocking = omnia_led_brightness_set_blocking; cdev->trigger_type = &omnia_hw_trigger_type; cdev->default_trigger = omnia_hw_trigger.name;Signature · 1 line
2.20.1Signature · 1 line
Lee Jones [李琼斯]
Quoted 9 lines · Pali Rohár
Linus Walleij suggested me to send these patches to SoC tree [1] instead. So I'm doing it.
This patch series contains LED patches which are on the linux-leds mailing list for a long time without any future movement. Could you please handle them here via SoC tree? Thanks.
I'm going through the backlog of patches sent to [email protected] and came across this series. While I don't mind taking these patches through the soc tree in principle, it is important that this is only done as an exception, and with all the relevant parties on Cc.
In particular, the original series that you got no feedback for did not include the arch/powerpc/ changes, and I would assume those should go through the powerpc tree anyway. We have recently decided to take risc-v and loongarch dts changes through the soc tree, and I don't mind doing it for powerpc as well if the powerpc maintainers prefer that, but this is not something we have even discussed so far.
I've added everyone to Cc on this mail, but please resend the series once more so everyone has the patches, and then we can decide who will pick up what.
Arnd
Quoted 42 lines
Marek Behún (3):
leds: turris-omnia: support HW controlled mode via private trigger
leds: turris-omnia: initialize multi-intensity to full
leds: turris-omnia: change max brightness from 255 to 1Pali Rohár (5):
dt-bindings: leds: register-bit-led: Add active-low property
leds: syscon: Implement support for active-low property powerpc/85xx: DTS: Add CPLD definitions for P1021RDB Combo Board CPL
Design
dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
leds: Add support for Turris 1.x LEDs.../testing/sysfs-class-led-driver-turris1x | 31 ++ .../bindings/leds/cznic,turris1x-leds.yaml | 118 +++++ .../bindings/leds/register-bit-led.yaml | 5 + arch/powerpc/boot/dts/fsl/p1020mbg-pc.dtsi | 92 ++++ arch/powerpc/boot/dts/fsl/p1020mbg-pc_32b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020mbg-pc_36b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020rdb-pd.dts | 44 +- arch/powerpc/boot/dts/fsl/p1020utm-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1020utm-pc_32b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1020utm-pc_36b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1021rdb-pc_32b.dts | 5 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc_36b.dts | 5 +- arch/powerpc/boot/dts/fsl/p2020rdb-pc.dtsi | 33 +- drivers/leds/Kconfig | 10 + drivers/leds/Makefile | 1 + drivers/leds/leds-syscon.c | 14 +- drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ drivers/leds/leds-turris-omnia.c | 46 +- 19 files changed, 945 insertions(+), 27 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-led-driver-turris1x create mode 100644 Documentation/devicetree/bindings/leds/cznic,turris1x-leds.yaml create mode 100644 drivers/leds/leds-turris-1x.cSignature · 1 line
2.20.1
Lee Jones
maintainerQuoted 26 lines · Arnd Bergmann
Quoted 9 lines · Pali Rohár
Linus Walleij suggested me to send these patches to SoC tree [1] instead. So I'm doing it.
This patch series contains LED patches which are on the linux-leds mailing list for a long time without any future movement. Could you please handle them here via SoC tree? Thanks.
I'm going through the backlog of patches sent to [email protected] and came across this series. While I don't mind taking these patches through the soc tree in principle, it is important that this is only done as an exception, and with all the relevant parties on Cc.
In particular, the original series that you got no feedback for did not include the
arch/powerpc/changes, and I would assume those should go through the powerpc tree anyway. We have recently decided to take risc-v and loongarch dts changes through the soc tree, and I don't mind doing it for powerpc as well if the powerpc maintainers prefer that, but this is not something we have even discussed so far.
Quoted 3 lines
I've added everyone to Cc on this mail, but please resend the series once more so everyone has the patches, and then we can decide who will pick up what.
Thanks Arnd (PSB).
Quoted 28 lines
Quoted 27 lines
Marek Behún (3):
leds: turris-omnia: support HW controlled mode via private trigger
leds: turris-omnia: initialize multi-intensity to full
leds: turris-omnia: change max brightness from 255 to 1Pali Rohár (5):
dt-bindings: leds: register-bit-led: Add active-low property
leds: syscon: Implement support for active-low property powerpc/85xx: DTS: Add CPLD definitions for P1021RDB Combo Board CPL
Design
dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
leds: Add support for Turris 1.x LEDs.../testing/sysfs-class-led-driver-turris1x | 31 ++ .../bindings/leds/cznic,turris1x-leds.yaml | 118 +++++ .../bindings/leds/register-bit-led.yaml | 5 + arch/powerpc/boot/dts/fsl/p1020mbg-pc.dtsi | 92 ++++ arch/powerpc/boot/dts/fsl/p1020mbg-pc_32b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020mbg-pc_36b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020rdb-pd.dts | 44 +- arch/powerpc/boot/dts/fsl/p1020utm-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1020utm-pc_32b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1020utm-pc_36b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1021rdb-pc_32b.dts | 5 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc_36b.dts | 5 +- arch/powerpc/boot/dts/fsl/p2020rdb-pc.dtsi | 33 +-
Quoted 5 lines
Quoted 5 lines
drivers/leds/Kconfig | 10 + drivers/leds/Makefile | 1 + drivers/leds/leds-syscon.c | 14 +- drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ drivers/leds/leds-turris-omnia.c | 46 +-
If everyone is convinced that applying these drivers is the correct thing to do, I'd be happy to (rather) take them via LEDs.
Signature · 1 line
Lee Jones [李琼斯]
Quoted 30 lines · Lee Jones
Quoted 27 lines · Arnd Bergmann
Quoted 27 lines
Marek Behún (3):
leds: turris-omnia: support HW controlled mode via private trigger
leds: turris-omnia: initialize multi-intensity to full
leds: turris-omnia: change max brightness from 255 to 1Pali Rohár (5):
dt-bindings: leds: register-bit-led: Add active-low property
leds: syscon: Implement support for active-low property powerpc/85xx: DTS: Add CPLD definitions for P1021RDB Combo Board CPL
Design
dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
leds: Add support for Turris 1.x LEDs.../testing/sysfs-class-led-driver-turris1x | 31 ++ .../bindings/leds/cznic,turris1x-leds.yaml | 118 +++++ .../bindings/leds/register-bit-led.yaml | 5 + arch/powerpc/boot/dts/fsl/p1020mbg-pc.dtsi | 92 ++++ arch/powerpc/boot/dts/fsl/p1020mbg-pc_32b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020mbg-pc_36b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020rdb-pd.dts | 44 +- arch/powerpc/boot/dts/fsl/p1020utm-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1020utm-pc_32b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1020utm-pc_36b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1021rdb-pc_32b.dts | 5 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc_36b.dts | 5 +- arch/powerpc/boot/dts/fsl/p2020rdb-pc.dtsi | 33 +-
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
drivers/leds/Kconfig | 10 + drivers/leds/Makefile | 1 + drivers/leds/leds-syscon.c | 14 +- drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ drivers/leds/leds-turris-omnia.c | 46 +-If everyone is convinced that applying these drivers is the correct thing to do, I'd be happy to (rather) take them via LEDs.
Ok, thanks. I had not actually looked at the patches until today. They were in the soc tree backlog but appeared to be misplaced there until I read the 0/10 message text.
Looking at it now, I see:
- patches 1 and 2 seem obvious and have been reviewed by others already
- patch 3 is for arch/powerpc and should get merged through there if there are no objections to the binding in patch 4.
- patch 5 is the big driver patch, with a Reviewed-by tag from Marek Behún, who is the author of the last three patches. An earlier version of this patch was sent in June and got a few Acks and detailed feedback from Andy [1], but he's also not on Cc, and I don't know if his comments are all resolved in this version.
- Patches 6, 7 and 8 all seem simple LED subsystem patches, they just need review from you in order to get applied. These are also missing a Signed-off-by from the submitter in addition to the author in order to be applied.
Arnd
[1] https://lore.kernel.org/all/CAHp75Vcr6o2rm+T6Tr8sS4VXCLVHtmLPWy-njOKAvO4AcZoW=A@mail.gmail.com/
Lee Jones
maintainerQuoted 59 lines · Arnd Bergmann
Quoted 30 lines · Lee Jones
Quoted 27 lines · Arnd Bergmann
Quoted 27 lines
Marek Behún (3):
leds: turris-omnia: support HW controlled mode via private trigger
leds: turris-omnia: initialize multi-intensity to full
leds: turris-omnia: change max brightness from 255 to 1Pali Rohár (5):
dt-bindings: leds: register-bit-led: Add active-low property
leds: syscon: Implement support for active-low property powerpc/85xx: DTS: Add CPLD definitions for P1021RDB Combo Board CPL
Design
dt-bindings: leds: Add cznic,turris1x-leds.yaml binding
leds: Add support for Turris 1.x LEDs.../testing/sysfs-class-led-driver-turris1x | 31 ++ .../bindings/leds/cznic,turris1x-leds.yaml | 118 +++++ .../bindings/leds/register-bit-led.yaml | 5 + arch/powerpc/boot/dts/fsl/p1020mbg-pc.dtsi | 92 ++++ arch/powerpc/boot/dts/fsl/p1020mbg-pc_32b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020mbg-pc_36b.dts | 6 +- arch/powerpc/boot/dts/fsl/p1020rdb-pd.dts | 44 +- arch/powerpc/boot/dts/fsl/p1020utm-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1020utm-pc_32b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1020utm-pc_36b.dts | 4 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc.dtsi | 37 ++ arch/powerpc/boot/dts/fsl/p1021rdb-pc_32b.dts | 5 +- arch/powerpc/boot/dts/fsl/p1021rdb-pc_36b.dts | 5 +- arch/powerpc/boot/dts/fsl/p2020rdb-pc.dtsi | 33 +-Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
drivers/leds/Kconfig | 10 + drivers/leds/Makefile | 1 + drivers/leds/leds-syscon.c | 14 +- drivers/leds/leds-turris-1x.c | 474 ++++++++++++++++++ drivers/leds/leds-turris-omnia.c | 46 +-If everyone is convinced that applying these drivers is the correct thing to do, I'd be happy to (rather) take them via LEDs.
Ok, thanks. I had not actually looked at the patches until today. They were in the soc tree backlog but appeared to be misplaced there until I read the 0/10 message text.
Looking at it now, I see:
- patches 1 and 2 seem obvious and have been reviewed by others already
- patch 3 is for
arch/powerpcand should get merged through there if there are no objections to the binding in patch 4.- patch 5 is the big driver patch, with a Reviewed-by tag from Marek Behún, who is the author of the last three patches. An earlier version of this patch was sent in June and got a few Acks and detailed feedback from Andy [1], but he's also not on Cc, and I don't know if his comments are all resolved in this version.
Quoted 4 lines
- Patches 6, 7 and 8 all seem simple LED subsystem patches, they just need review from you in order to get applied. These are also missing a Signed-off-by from the submitter in addition to the author in order to be applied.
Very well. Let's have them resent then please (with past reviewers on Cc:) and we'll go from there.
Signature · 1 line
Lee Jones [李琼斯]
Quoted 2 lines · Lee Jones
If everyone is convinced that applying these drivers is the correct thing to do, I'd be happy to (rather) take them via LEDs.
Oh you are co-maintainer of the LED subsystem since a month!
Sadly this series stalled way before that, so that's why we didn't notice.
By all means, pick it up!
Yours,
Linus Walleij