According to https://svanheule.net/switches/_media/undefined/hasivo_8port_pse_application_description-re.docx, register 0x0c should be the chip status and it should read 0x91, but in this case it looks like it is register 0x09. So, reading 0x09 should return 0x91 if the chip is there and on. Again though, this is the STC8 and not the PoE chip that this document is really for, so who knows for sure.
From 0x2a to 0x2d is only like 0..3 change in value, whilst I'd expect a greater than 3degC change in temperature. Makes me think maybe it's not temperature afterall... maybe it's like a temperature range, or similar. Do you recall if the stock firmware showed up any temperature indication in the webui for 'case' or similar (i.e. not CPU)?
I suspect that register 0x09 as 0x91 is something written by the RTL host as a configuration value, as some kind of config for the STC8. Similar to the 0x40 in 0x07 and 0x08.
I tried booting my board without the PoE daughterboard attached, and sure enough i2c devids 0x0d and 0x15 disappeared, leaving me with just the 0x4d. So I think we've got the allocations right.. 0x0d and 0x15 are the PoE chips, and 0x4d is the STC8.
I didn't get much progress last night, but will give it a few more hours tonight.
I'll focus on getting a "hasivo,stc8-mfd" syscon/mfd driver, which would then allow the PoE LEDs to get exposed.
And then will look to get the PSE subsystem in for the Hasivo HS104 driver.
Remember that the sensor is only measuring ambient temperature, it’s not directly on the PHY. It followed VERY closely to the CPU temp going up/down.
If it is 1degC increments, that doesn't quite explain the offset. Whilst I've got 40+degC here, you mentioned you were more like 20degC.
If we said that each increment was 0.5degC, that means it was 21degC ambient, going up to 22.5degC with CPU under load. Doesn't seem like such a big change... but I guess that depends on airflow etc.
Any chance you've had some more time to open the firmware in Ghidra?
What I'm currently a bit confused about is where the reads/writes to the STC8 are.
The i2c_byte_get seems to specifically prevent reads from i2c devids >= 0x20.
And when I look around for other dev_i2c_read / dev_i2c_write instances I come up moderately empty... there are a bunch of them associated with fiber connections, but I expect this is SFP-type stuff (SFP has I2C bus for the identifcation EEPROM). But nothing else.
And I've looked through all of the modules in my firmware image.
Any ideas on where other accesses might be (and how to find them)?
Sorry @bevanweiss I would love to help and read here every day about the progress. Congrats! But I can't manage it during the week - that weekend is fully booked for this project;-) I try to help as much as possible on Saturday... best
Ok, I've made a tiny bit of progress...
If you bring in the commit from each of these branches, then you should get something that can at least expose and control the LEDs like a normal linux LED... i.e. you can set the brightness of it like below:
root@OpenWrt:~# cd /sys/class/leds/
root@OpenWrt:/sys/class/leds# ls
green:system led_lan2_poe led_lan4_poe led_lan6_poe led_lan8_poe
led_lan1_poe led_lan3_poe led_lan5_poe led_lan7_poe
root@OpenWrt:/sys/class/leds# cd led_lan1_poe/
root@OpenWrt:/sys/class/leds/led_lan1_poe# ls
brightness max_brightness trigger
device subsystem uevent
root@OpenWrt:/sys/class/leds/led_lan1_poe# echo 255 > brightness
root@OpenWrt:/sys/class/leds/led_lan1_poe# echo 0 > brightness
root@OpenWrt:/sys/class/leds/led_lan1_poe# cd ..
root@OpenWrt:/sys/class/leds# echo 255 > led_lan8_poe/brightness
root@OpenWrt:/sys/class/leds# echo 0 > led_lan8_poe/brightness
root@OpenWrt:/sys/class/leds#
Importantly that should also mean that it can get assigned to a trigger, like the proposed PoE triggers for either enabled / delivering power.. or any other options we'd like to expose.
I'll see what I can get for the PoE itself tomorrow.
One item I have seen in my testing here is that my PHYs appear to not be coming up. Which might be that the device tree for them is a bit wrong now.. although it had been working ok before. I'll look into this again once I've made some progress on the PoE stuff.
I’ll be happy to test here too when it’s ready.
regarding the stock firmware and devids => 0x20:
This prevention is also in rtcore again, from what I saw:
And the drv_i2c_write in rtcore is used by dev_i2c_write in ski.ko. So they prevent it two times.
It looks pretty similar to this piece:
if(i2c_dev_id >= I2C_DEV_ID_END) in https://github.com/plappermaul/realtek-doc/blob/30e7d6c8c246d66538dc1288986b84674e23dcac/sources/rtk-dms1250/system/drv/i2c/i2c.c#L200
The only thing that could look interesting is drv_software_i2c_write, but this requires more investigation....
@bevanweiss is this really the right commit? I took both commits on latest openwrt branch and run into some issues: a) it did not compile because of wrong kernel version (pse module), but this I could fix with some lines ... b) the module is not initialized c) no poe leds in sys, but via i2c_set, they are working d) no network, as you said
I guess I wait for you, before I get lost in the rabbit hole ![]()
Two commits, you'd need to cherry-pick to get them both.
PSE shouldn't be a factor in this set at all. Since there's no PoE device in these two commits (only the hs104 referenced in the devicetree, but no driver for it, so it should just be ignored).
Maybe I've messed up the PHY configs in the device tree. But I think the only changes there are the mode as "sgmii" and the in-band managed from the RTL8221b discussions in Github.
The PSE backports are causing me more trouble than I expected. So likely no progress on the HS104 driver this weekend, I want to get all the PSE stuff in so the driver can target this first.
That's a different check. That's looking at param_1 of drv_i2c_read, which is always 0 from the i2c_byte_get function. So that's about which I2C 'master' to use.
The check I referenced was for which I2C 'slave' to allow.. so i2c_byte_get couldn't be used for the STC8 chip (at 0x4d) since it only allows up to 0x20.
Hi guys,
- I made some progress and have first fully running version (POE on-off on all ports, LED support and control via pse stuff + ethtool). Long day with a lot of tryouts, googling, LLMs and whatever you find online.
-
Btw, For network, I used the openwrt version from 10 days ago, because it was working already. So Maybe this requires another investigation after rebase...
I decided to change a little how LED control works, which is also similar (at least what I think) to the stock firmware. You can define the LEDs in the DTS, also you can define multiple hs104 chips in DTS, as @bevanweiss started it. -
In simple it works like this, and the poll thingy is similar to the stock firmware:
* hs104 polls POE power status every 500ms
* reads register 0x01 (which ports have poe on)
* if port status changed → fires LED trigger event
* Example: "0-000d:port0_delivering" → led_on or led_off
* kernel LED subsystem receives trigger event
* finds LED subscribed to that trigger (defined in DTS)
* calls stc8_led_set() in stc8-mfd driver
* stc8 driver writes to I2C register (0x01 or 0x02) with the correct bit mask to turn LED on/off
* so the orange LED is on (or off)
- 1 DTS setup:
HS104 creates trigger: "0-000d:port0_delivering"
↓
(kernel matches)
↓
STC8 LED subscribes: linux,default-trigger = "0-000d:port0_delivering"
-
I tried to cleanup a little. But there is still some code smell, and hacky stuff. Especially as I have never worked on such a driver before. I also did not test power limits or other complicated stuff: just reading current power, switching on and off + LEDs... This seems to work.
-
My biggest question is this patch, which is a result of multiple times google, LLM and different try outs. It works like this, but maybe some folks have a proposal to make it better?
- Some results, to see it in action.
root@OpenWrt:~# ethtool --show-pse lan4
PSE attributes for lan4:
Clause 33 PSE Admin State: enabled
Clause 33 PSE Power Detection Status: delivering power
Clause 33 PSE Power Class: 4
Clause 33 PSE Actual Power: 9390
Clause 33 PSE Available Power Limit: 30000
min 15400
max 15400
min 30000
max 30000
min 60000
max 60000
min 90000
max 90000
root@OpenWrt:~# ethtool --show-pse lan4
PSE attributes for lan4:
Clause 33 PSE Admin State: enabled
Clause 33 PSE Power Detection Status: delivering power
Clause 33 PSE Power Class: 4
Clause 33 PSE Actual Power: 9530
Clause 33 PSE Available Power Limit: 30000
min 15400
max 15400
min 30000
max 30000
min 60000
max 60000
min 90000
max 90000
root@OpenWrt:~# ethtool --set-pse lan4 c33-pse-admin-control disable
root@OpenWrt:~# [ 137.214169] rtl83xx-switch switch@1b000000 lan4: Link is Down
[ 137.233497] switch: port 4(lan4) entered disabled state
root@OpenWrt:~# ethtool --show-pse lan4
PSE attributes for lan4:
Clause 33 PSE Admin State: disabled
Clause 33 PSE Power Detection Status: disabled
Clause 33 PSE Power Class: 20
Clause 33 PSE Available Power Limit: 30000
min 15400
max 15400
min 30000
max 30000
min 60000
max 60000
min 90000
max 90000
root@OpenWrt:~# ethtool --set-pse lan4 c33-pse-admin-control enable
root@OpenWrt:~# [ 162.174756] rtl83xx-switch switch@1b000000 lan4: Link is Up - 2.5Gbps/Full - flow control rx/tx
[ 162.203714] switch: port 4(lan4) entered blocking state
[ 162.221151] switch: port 4(lan4) entered forwarding state
root@OpenWrt:~# ethtool --show-pse lan4
PSE attributes for lan4:
Clause 33 PSE Admin State: enabled
Clause 33 PSE Power Detection Status: delivering power
Clause 33 PSE Power Class: 4
Clause 33 PSE Actual Power: 4710
Clause 33 PSE Available Power Limit: 30000
min 15400
max 15400
min 30000
max 30000
min 60000
max 60000
min 90000
max 90000
Big thx to @bevanweiss for all the previous work here. I owe you one! ... I apologize for changing the LEDs (2.5G, 1G , 100M)
The stock firmware and the stickers on the device were too tempting. Also I am back to 34000 baud ![]()
If anyone wants to test, fell free!
Awesome work. I'll have a look into running it up on my switch tonight.
I'm not sure about the changes to the MFD to require additional drivers for the LEDs etc. I'd hope that if we can get info on fan / thermal controls then we'd gain another device to add as a child, and GPIO ditto..
Did you try it with the master branch for the switch port link stuff?
That is awesome ![]()
So straight away I've loaded up luci to have a look at how pretty it could be for these switches.
I do wonder if perhaps we should have stuff configured for the LED Configuration section.
We can default things to as per the vendor, but ultimately if we can give the end users more configurability it would be great.
Which I actually think might be a luci deficiency. It should enumerate the existing LEDs and show their triggers I reckon...
They are exposed as expected..
But then there's no drop down available for it..
Even though the triggers themselves do show up...
root@OpenWrt:/sys# cat /sys/class/leds/orange:lan1_poe/trigger
none timer heartbeat default-on netdev 0-000d:port0_delivering [0-000d:port0_enabled] 0-000d:port1_delivering 0-000d:port1_enabled 0-000d:port2_delivering 0-000d:port2_enabled 0-000d:port3_delivering 0-000d:port3_enabled 0-0015:port0_delivering 0-0015:port0_enabled 0-0015:port1_delivering 0-0015:port1_enabled 0-0015:port2_delivering 0-0015:port2_enabled 0-0015:port3_delivering 0-0015:port3_enabled
I wonder if linux upstream maybe needs some love on PSE-PD LED triggers. Perhaps having it like netdev might be an idea... where it gets a top level trigger pse-pd, which then presents a bunch of device_name options, and some certain activities.
root@OpenWrt:/sys/class/leds/orange:lan1_poe# echo netdev > trigger
root@OpenWrt:/sys/class/leds/orange:lan1_poe# ls -l
-rw-r--r-- 1 root root 4096 Jan 1 1970 brightness
lrwxrwxrwx 1 root root 0 Jan 12 09:27 device -> ../../../0-004d
-rw-r--r-- 1 root root 4096 Jan 12 09:35 device_name
-rw-r--r-- 1 root root 4096 Jan 12 09:35 full_duplex
-rw-r--r-- 1 root root 4096 Jan 12 09:35 half_duplex
-rw-r--r-- 1 root root 4096 Jan 12 09:35 interval
-rw-r--r-- 1 root root 4096 Jan 12 09:35 link
-r--r--r-- 1 root root 4096 Jan 1 1970 max_brightness
-r--r--r-- 1 root root 4096 Jan 12 09:35 offloaded
-rw-r--r-- 1 root root 4096 Jan 12 09:35 rx
-rw-r--r-- 1 root root 4096 Jan 12 09:35 rx_err
lrwxrwxrwx 1 root root 0 Jan 12 09:27 subsystem -> ../../../../../../../class/leds
-rw-r--r-- 1 root root 0 Jan 12 09:35 trigger
-rw-r--r-- 1 root root 4096 Jan 12 09:35 tx
-rw-r--r-- 1 root root 4096 Jan 12 09:35 tx_err
-rw-r--r-- 1 root root 4096 Jan 12 09:27 uevent
And probably the Realtek chips themselves should have the LED configuration exposed in this same manner, rather than hidden as a build time only setting in the device tree.
Hi,
Thanks for trying it out @bevanweiss
During the week I won't have much time.
Next weekend I will reply to all your points and incorporate your github comments ! Awesome collaboration, thx!
I let you know when I have progress...
For Luci - I guess we have to add poe support to netifd to support uci and finally luci... Then we would have support for modern "modern 802.3bt/Clause 33 PSE" ...
But that is not done in a minute ![]()
Going with scripts and some user based application (instead of ethtool) to manage the poe ports sounds not proper.
I think having a ubus interface into netlink, which can then access the ethtool elements, is probably one such way.
I'm working on this at the moment. It'll support get / set / dump type of actions.



